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
 
@@ -22,7 +23,7 @@ class CollectionSelectInputTest < ActionView::TestCase
22
23
  end
23
24
 
24
25
  test 'input allows overriding collection for select types' do
25
- with_input_for @user, :name, :select, collection: ['Jose', 'Carlos']
26
+ with_input_for @user, :name, :select, collection: %w[Jose Carlos]
26
27
  assert_select 'select.select#user_name'
27
28
  assert_select 'select option', 'Jose'
28
29
  assert_select 'select option', 'Carlos'
@@ -30,9 +31,9 @@ class CollectionSelectInputTest < ActionView::TestCase
30
31
 
31
32
  test 'input does automatic collection translation for select types using defaults key' do
32
33
  store_translations(:en, simple_form: { options: { defaults: {
33
- gender: { male: 'Male', female: 'Female'}
34
+ gender: { male: 'Male', female: 'Female' }
34
35
  } } }) do
35
- with_input_for @user, :gender, :select, collection: [:male, :female]
36
+ with_input_for @user, :gender, :select, collection: %i[male female]
36
37
  assert_select 'select.select#user_gender'
37
38
  assert_select 'select option', 'Male'
38
39
  assert_select 'select option', 'Female'
@@ -41,9 +42,9 @@ class CollectionSelectInputTest < ActionView::TestCase
41
42
 
42
43
  test 'input does automatic collection translation for select types using specific object key' do
43
44
  store_translations(:en, simple_form: { options: { user: {
44
- gender: { male: 'Male', female: 'Female'}
45
+ gender: { male: 'Male', female: 'Female' }
45
46
  } } }) do
46
- with_input_for @user, :gender, :select, collection: [:male, :female]
47
+ with_input_for @user, :gender, :select, collection: %i[male female]
47
48
  assert_select 'select.select#user_gender'
48
49
  assert_select 'select option', 'Male'
49
50
  assert_select 'select option', 'Female'
@@ -52,7 +53,7 @@ class CollectionSelectInputTest < ActionView::TestCase
52
53
 
53
54
  test 'input marks the selected value by default' do
54
55
  @user.name = "Carlos"
55
- with_input_for @user, :name, :select, collection: ['Jose', 'Carlos']
56
+ with_input_for @user, :name, :select, collection: %w[Jose Carlos]
56
57
  assert_select 'select option[selected=selected]', 'Carlos'
57
58
  end
58
59
 
@@ -113,7 +114,7 @@ class CollectionSelectInputTest < ActionView::TestCase
113
114
 
114
115
  test 'input translates include blank with a default' do
115
116
  store_translations(:en, simple_form: { include_blanks: { defaults: {
116
- age: 'Rather not say',
117
+ age: 'Rather not say'
117
118
  } } }) do
118
119
  with_input_for @user, :age, :select, collection: 18..30, include_blank: :translate
119
120
  assert_select 'select option[value=""]', 'Rather not say'
@@ -182,7 +183,7 @@ class CollectionSelectInputTest < ActionView::TestCase
182
183
 
183
184
  test 'input translates prompt with a default' do
184
185
  store_translations(:en, simple_form: { prompts: { defaults: {
185
- age: 'Select age:',
186
+ age: 'Select age:'
186
187
  } } }) do
187
188
  with_input_for @user, :age, :select, collection: 18..30, prompt: :translate
188
189
  assert_select 'select option[value=""]', 'Select age:'
@@ -224,7 +225,7 @@ class CollectionSelectInputTest < ActionView::TestCase
224
225
  end
225
226
 
226
227
  test 'input disables the anothers components when the option is a object' do
227
- with_input_for @user, :description, :select, collection: ["Jose", "Carlos"], disabled: true
228
+ with_input_for @user, :description, :select, collection: %w[Jose Carlos], disabled: true
228
229
  assert_no_select 'select option[value=Jose][disabled=disabled]', 'Jose'
229
230
  assert_no_select 'select option[value=Carlos][disabled=disabled]', 'Carlos'
230
231
  assert_select 'select[disabled=disabled]'
@@ -232,7 +233,7 @@ class CollectionSelectInputTest < ActionView::TestCase
232
233
  end
233
234
 
234
235
  test 'input does not disable the anothers components when the option is a object' do
235
- with_input_for @user, :description, :select, collection: ["Jose", "Carlos"], disabled: 'Jose'
236
+ with_input_for @user, :description, :select, collection: %w[Jose Carlos], disabled: 'Jose'
236
237
  assert_select 'select option[value=Jose][disabled=disabled]', 'Jose'
237
238
  assert_no_select 'select option[value=Carlos][disabled=disabled]', 'Carlos'
238
239
  assert_no_select 'select[disabled=disabled]'
@@ -241,126 +242,126 @@ class CollectionSelectInputTest < ActionView::TestCase
241
242
 
242
243
  test 'input allows overriding label and value method using a lambda for collection selects' do
243
244
  with_input_for @user, :name, :select,
244
- collection: ['Jose', 'Carlos'],
245
- label_method: lambda { |i| i.upcase },
246
- value_method: lambda { |i| i.downcase }
245
+ collection: %w[Jose Carlos],
246
+ label_method: ->(i) { i.upcase },
247
+ value_method: ->(i) { i.downcase }
247
248
  assert_select 'select option[value=jose]', "JOSE"
248
249
  assert_select 'select option[value=carlos]', "CARLOS"
249
250
  end
250
251
 
251
252
  test 'input allows overriding only label but not value method using a lambda for collection select' do
252
253
  with_input_for @user, :name, :select,
253
- collection: ['Jose', 'Carlos'],
254
- label_method: lambda { |i| i.upcase }
254
+ collection: %w[Jose Carlos],
255
+ label_method: ->(i) { i.upcase }
255
256
  assert_select 'select option[value=Jose]', "JOSE"
256
257
  assert_select 'select option[value=Carlos]', "CARLOS"
257
258
  end
258
259
 
259
260
  test 'input allows overriding only value but not label method using a lambda for collection select' do
260
261
  with_input_for @user, :name, :select,
261
- collection: ['Jose', 'Carlos'],
262
- value_method: lambda { |i| i.downcase }
262
+ collection: %w[Jose Carlos],
263
+ value_method: ->(i) { i.downcase }
263
264
  assert_select 'select option[value=jose]', "Jose"
264
265
  assert_select 'select option[value=carlos]', "Carlos"
265
266
  end
266
267
 
267
268
  test 'input allows symbols for collections' do
268
- with_input_for @user, :name, :select, collection: [:jose, :carlos]
269
+ with_input_for @user, :name, :select, collection: %i[jose carlos]
269
270
  assert_select 'select.select#user_name'
270
271
  assert_select 'select option[value=jose]', 'jose'
271
272
  assert_select 'select option[value=carlos]', 'carlos'
272
273
  end
273
274
 
274
275
  test 'collection input with select type generates required html attribute only with blank option' do
275
- with_input_for @user, :name, :select, include_blank: true, collection: ['Jose', 'Carlos']
276
+ with_input_for @user, :name, :select, include_blank: true, collection: %w[Jose Carlos]
276
277
  assert_select 'select.required'
277
278
  assert_select 'select[required]'
278
279
  end
279
280
 
280
281
  test 'collection input with select type generates required html attribute only with blank option or prompt' do
281
- with_input_for @user, :name, :select, prompt: 'Name...', collection: ['Jose', 'Carlos']
282
+ with_input_for @user, :name, :select, prompt: 'Name...', collection: %w[Jose Carlos]
282
283
  assert_select 'select.required'
283
284
  assert_select 'select[required]'
284
285
  end
285
286
 
286
287
  test 'collection input with select type does not generate required html attribute without blank option' do
287
- with_input_for @user, :name, :select, include_blank: false, collection: ['Jose', 'Carlos']
288
+ with_input_for @user, :name, :select, include_blank: false, collection: %w[Jose Carlos]
288
289
  assert_select 'select.required'
289
290
  assert_no_select 'select[required]'
290
291
  assert_no_select 'select[aria-required=true]'
291
292
  end
292
293
 
293
294
  test 'collection input with select type with multiple attribute generates required html attribute without blank option' do
294
- with_input_for @user, :name, :select, include_blank: false, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
295
+ with_input_for @user, :name, :select, include_blank: false, input_html: { multiple: true }, collection: %w[Jose Carlos]
295
296
  assert_select 'select.required'
296
297
  assert_select 'select[required]'
297
298
  end
298
299
 
299
300
  test 'collection input with select type with multiple attribute generates required html attribute with blank option' do
300
- with_input_for @user, :name, :select, include_blank: true, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
301
+ with_input_for @user, :name, :select, include_blank: true, input_html: { multiple: true }, collection: %w[Jose Carlos]
301
302
  assert_select 'select.required'
302
303
  assert_select 'select[required]'
303
304
  end
304
305
 
305
306
  test 'with a blank option, a collection input of type select has an aria-required html attribute' do
306
- with_input_for @user, :name, :select, include_blank: true, collection: ['Jose', 'Carlos']
307
+ with_input_for @user, :name, :select, include_blank: true, collection: %w[Jose Carlos]
307
308
  assert_select 'select.required'
308
309
  assert_select 'select[aria-required=true]'
309
310
  end
310
311
 
311
312
  test 'without a blank option, a collection input of type select does not have an aria-required html attribute' do
312
- with_input_for @user, :name, :select, include_blank: false, collection: ['Jose', 'Carlos']
313
+ with_input_for @user, :name, :select, include_blank: false, collection: %w[Jose Carlos]
313
314
  assert_select 'select.required'
314
315
  assert_no_select 'select[aria-required]'
315
316
  end
316
317
 
317
318
  test 'without a blank option and with a multiple option, a collection input of type select has an aria-required html attribute' do
318
- with_input_for @user, :name, :select, include_blank: false, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
319
+ with_input_for @user, :name, :select, include_blank: false, input_html: { multiple: true }, collection: %w[Jose Carlos]
319
320
  assert_select 'select.required'
320
321
  assert_select 'select[aria-required=true]'
321
322
  end
322
323
 
323
324
  test 'with a blank option and a multiple option, a collection input of type select has an aria-required html attribute' do
324
- with_input_for @user, :name, :select, include_blank: true, input_html: { multiple: true }, collection: ['Jose', 'Carlos']
325
+ with_input_for @user, :name, :select, include_blank: true, input_html: { multiple: true }, collection: %w[Jose Carlos]
325
326
  assert_select 'select.required'
326
327
  assert_select 'select[aria-required]'
327
328
  end
328
329
 
329
330
  test 'input allows disabled options with a lambda for collection select' do
330
- with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
331
- disabled: lambda { |x| x == "Carlos" }
331
+ with_input_for @user, :name, :select, collection: %w[Carlos Antonio],
332
+ disabled: ->(x) { x == "Carlos" }
332
333
  assert_select 'select option[value=Carlos][disabled=disabled]', 'Carlos'
333
334
  assert_select 'select option[value=Antonio]', 'Antonio'
334
335
  assert_no_select 'select option[value=Antonio][disabled]'
335
336
  end
336
337
 
337
338
  test 'input allows disabled and label method with lambdas for collection select' do
338
- with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
339
- disabled: lambda { |x| x == "Carlos" }, label_method: lambda { |x| x.upcase }
339
+ with_input_for @user, :name, :select, collection: %w[Carlos Antonio],
340
+ disabled: ->(x) { x == "Carlos" }, label_method: ->(x) { x.upcase }
340
341
  assert_select 'select option[value=Carlos][disabled=disabled]', 'CARLOS'
341
342
  assert_select 'select option[value=Antonio]', 'ANTONIO'
342
343
  assert_no_select 'select option[value=Antonio][disabled]'
343
344
  end
344
345
 
345
346
  test 'input allows a non lambda disabled option with lambda label method for collections' do
346
- with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
347
- disabled: "Carlos", label_method: lambda { |x| x.upcase }
347
+ with_input_for @user, :name, :select, collection: %w[Carlos Antonio],
348
+ disabled: "Carlos", label_method: ->(x) { x.upcase }
348
349
  assert_select 'select option[value=Carlos][disabled=disabled]', 'CARLOS'
349
350
  assert_select 'select option[value=Antonio]', 'ANTONIO'
350
351
  assert_no_select 'select option[value=Antonio][disabled]'
351
352
  end
352
353
 
353
354
  test 'input allows selected and label method with lambdas for collection select' do
354
- with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
355
- selected: lambda { |x| x == "Carlos" }, label_method: lambda { |x| x.upcase }
355
+ with_input_for @user, :name, :select, collection: %w[Carlos Antonio],
356
+ selected: ->(x) { x == "Carlos" }, label_method: ->(x) { x.upcase }
356
357
  assert_select 'select option[value=Carlos][selected=selected]', 'CARLOS'
357
358
  assert_select 'select option[value=Antonio]', 'ANTONIO'
358
359
  assert_no_select 'select option[value=Antonio][selected]'
359
360
  end
360
361
 
361
362
  test 'input allows a non lambda selected option with lambda label method for collection select' do
362
- with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
363
- selected: "Carlos", label_method: lambda { |x| x.upcase }
363
+ with_input_for @user, :name, :select, collection: %w[Carlos Antonio],
364
+ selected: "Carlos", label_method: ->(x) { x.upcase }
364
365
  assert_select 'select option[value=Carlos][selected=selected]', 'CARLOS'
365
366
  assert_select 'select option[value=Antonio]', 'ANTONIO'
366
367
  assert_no_select 'select option[value=Antonio][selected]'
@@ -368,8 +369,8 @@ class CollectionSelectInputTest < ActionView::TestCase
368
369
 
369
370
  test 'input does not override default selection through attribute value with label method as lambda for collection select' do
370
371
  @user.name = "Carlos"
371
- with_input_for @user, :name, :select, collection: ["Carlos", "Antonio"],
372
- label_method: lambda { |x| x.upcase }
372
+ with_input_for @user, :name, :select, collection: %w[Carlos Antonio],
373
+ label_method: ->(x) { x.upcase }
373
374
  assert_select 'select option[value=Carlos][selected=selected]', 'CARLOS'
374
375
  assert_select 'select option[value=Antonio]', 'ANTONIO'
375
376
  assert_no_select 'select option[value=Antonio][selected]'
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class ColorInputTest < ActionView::TestCase
6
+ test 'input generates a color field' do
7
+ with_input_for @user, :favorite_color, :color
8
+ assert_select 'input[type=color].color#user_favorite_color'
9
+ end
10
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -5,8 +6,7 @@ require 'test_helper'
5
6
  class DateTimeInputWithHtml5Test < ActionView::TestCase
6
7
  test 'input generates a datetime input for datetime attributes if HTML5 compatibility is explicitly enbled' do
7
8
  with_input_for @user, :created_at, :datetime, html5: true
8
-
9
- assert_select 'input[type="datetime"]'
9
+ assert_select 'input[type="datetime-local"]'
10
10
  end
11
11
 
12
12
  test 'input generates a datetime select for datetime attributes' do
@@ -75,8 +75,7 @@ class DateTimeInputWithoutHtml5Test < ActionView::TestCase
75
75
  test 'input generates a datetime input for datetime attributes if HTML5 compatibility is explicitly enabled' do
76
76
  swap_wrapper do
77
77
  with_input_for @user, :created_at, :datetime, html5: true
78
-
79
- assert_select 'input[type="datetime"]'
78
+ assert_select 'input[type="datetime-local"]'
80
79
  end
81
80
  end
82
81
 
@@ -142,26 +141,26 @@ class DateTimeInputWithoutHtml5Test < ActionView::TestCase
142
141
  end
143
142
 
144
143
  test 'label uses i18n to get target for date input type' do
145
- store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
144
+ store_translations(:en, date: { order: %w[month day year] }) do
146
145
  with_input_for :project, :created_at, :date, html5: false
147
146
  assert_select 'label[for=project_created_at_2i]'
148
147
  end
149
148
  end
150
149
 
151
150
  test 'label uses i18n to get target for datetime input type' do
152
- store_translations(:en, date: { order: ['month', 'day', 'year'] }) do
151
+ store_translations(:en, date: { order: %w[month day year] }) do
153
152
  with_input_for :project, :created_at, :datetime, html5: false
154
153
  assert_select 'label[for=project_created_at_2i]'
155
154
  end
156
155
  end
157
156
 
158
157
  test 'label uses order to get target when date input type' do
159
- with_input_for :project, :created_at, :date, order: ['month', 'year', 'day'], html5: false
158
+ with_input_for :project, :created_at, :date, order: %w[month year day], html5: false
160
159
  assert_select 'label[for=project_created_at_2i]'
161
160
  end
162
161
 
163
162
  test 'label uses order to get target when datetime input type' do
164
- with_input_for :project, :created_at, :datetime, order: ['month', 'year', 'day'], html5: false
163
+ with_input_for :project, :created_at, :datetime, order: %w[month year day], html5: false
165
164
  assert_select 'label[for=project_created_at_2i]'
166
165
  end
167
166
 
@@ -169,4 +168,9 @@ class DateTimeInputWithoutHtml5Test < ActionView::TestCase
169
168
  with_input_for :project, :created_at, :time, html5: false
170
169
  assert_select 'label[for=project_created_at_4i]'
171
170
  end
171
+
172
+ test 'label points to attribute name if HTML5 compatibility is explicitly enabled' do
173
+ with_input_for :project, :created_at, :date, html5: true
174
+ assert_select 'label[for=project_created_at]'
175
+ end
172
176
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class DisabledTest < ActionView::TestCase
@@ -75,4 +76,17 @@ class DisabledTest < ActionView::TestCase
75
76
  with_input_for @user, :created_at, :datetime
76
77
  assert_no_select 'select.datetime.disabled[disabled]'
77
78
  end
79
+
80
+ test 'input_field collection allows disabled select' do
81
+ with_input_field_for @user, :description, collection: ['foo', 'bar'], disabled: true
82
+ assert_select 'select[disabled]'
83
+ assert_no_select 'option[disabled]'
84
+ end
85
+
86
+ test 'input_field collection allows individual disabled options' do
87
+ with_input_field_for @user, :description, collection: ['foo', 'bar'], disabled: 'bar'
88
+ assert_no_select 'select[disabled]'
89
+ assert_no_select 'option[disabled][value=foo]'
90
+ assert_select 'option[disabled][value=bar]'
91
+ end
78
92
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class DiscoveryTest < ActionView::TestCase
@@ -14,6 +15,8 @@ class DiscoveryTest < ActionView::TestCase
14
15
  Object.send :remove_const, :CustomizedInput
15
16
  Object.send :remove_const, :DeprecatedInput
16
17
  Object.send :remove_const, :CollectionSelectInput
18
+ Object.send :remove_const, :FileInput
19
+ CustomInputs.send :remove_const, :CustomizedInput
17
20
  CustomInputs.send :remove_const, :PasswordInput
18
21
  CustomInputs.send :remove_const, :NumericInput
19
22
  end
@@ -107,6 +110,26 @@ class DiscoveryTest < ActionView::TestCase
107
110
  end
108
111
  end
109
112
 
113
+ test 'does not duplicate the html classes giving a extra class' do
114
+ discovery do
115
+ swap SimpleForm, input_class: 'custom-default-input-class' do
116
+ with_form_for @user, :active, as: :select
117
+ assert_select 'form select#user_active.select' do
118
+ # Make sure class list contains 'chosen' only once.
119
+ assert_select ":match('class', ?)", /^(?!.*\bchosen\b.*\bchosen\b).*\bchosen\b.*$/
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ test 'new inputs can override the default input_html_classes' do
126
+ discovery do
127
+ with_form_for @user, :avatar, as: :file
128
+ assert_no_select 'form input[type=file]#user_avatar.file.file-upload'
129
+ assert_select 'form input[type=file]#user_avatar.file-upload'
130
+ end
131
+ end
132
+
110
133
  test 'inputs method without wrapper_options are deprecated' do
111
134
  discovery do
112
135
  assert_deprecated do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -119,12 +120,12 @@ class InputTest < ActionView::TestCase
119
120
  end
120
121
 
121
122
  test 'input as select with collection is generated properly when object is not present' do
122
- with_input_for :project, :name, :select, collection: ['Jose', 'Carlos']
123
+ with_input_for :project, :name, :select, collection: %w[Jose Carlos]
123
124
  assert_select 'select.select#project_name'
124
125
  end
125
126
 
126
127
  test 'input does not generate empty css class' do
127
- swap SimpleForm, generate_additional_classes_for: [:wrapper, :label] do
128
+ swap SimpleForm, generate_additional_classes_for: %i[wrapper label] do
128
129
  with_input_for :project, :name, :string
129
130
  assert_no_select 'input#project_name[class]'
130
131
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
4
5
  class GroupedCollectionSelectInputTest < ActionView::TestCase
5
6
  test 'grouped collection accepts array collection form' do
6
7
  with_input_for @user, :tag_ids, :grouped_select,
7
- collection: [['Authors', ['Jose', 'Carlos']], ['General', ['Bob', 'John']]],
8
+ collection: [['Authors', %w[Jose Carlos]], ['General', %w[Bob John]]],
8
9
  group_method: :last
9
10
 
10
11
  assert_select 'select.grouped_select#user_tag_ids' do
@@ -31,7 +32,7 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
31
32
 
32
33
  test 'grouped collection accepts proc as collection' do
33
34
  with_input_for @user, :tag_ids, :grouped_select,
34
- collection: Proc.new { [['Authors', ['Jose', 'Carlos']], ['General', ['Bob', 'John']]] },
35
+ collection: proc { [['Authors', %w[Jose Carlos]], ['General', %w[Bob John]]] },
35
36
  group_method: :last
36
37
 
37
38
  assert_select 'select.grouped_select#user_tag_ids' do
@@ -49,7 +50,7 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
49
50
 
50
51
  test 'grouped collection accepts hash collection form' do
51
52
  with_input_for @user, :tag_ids, :grouped_select,
52
- collection: { 'Authors' => ['Jose', 'Carlos'], 'General' => ['Bob', 'John'] },
53
+ collection: { Authors: %w[Jose Carlos], General: %w[Bob John] },
53
54
  group_method: :last
54
55
 
55
56
  assert_select 'select.grouped_select#user_tag_ids' do
@@ -67,7 +68,7 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
67
68
 
68
69
  test 'grouped collection accepts group_label_method option' do
69
70
  with_input_for @user, :tag_ids, :grouped_select,
70
- collection: { ['Jose', 'Carlos'] => 'Authors' },
71
+ collection: { %w[Jose Carlos] => 'Authors' },
71
72
  group_method: :first,
72
73
  group_label_method: :last
73
74
 
@@ -80,7 +81,7 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
80
81
  end
81
82
 
82
83
  test 'grouped collection finds default label methods on the group objects' do
83
- option_list = ['Jose', 'Carlos']
84
+ option_list = %w[Jose Carlos]
84
85
 
85
86
  GroupedClass = Struct.new(:to_label, :options)
86
87
  group = GroupedClass.new("Authors", option_list)
@@ -117,7 +118,7 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
117
118
 
118
119
  test 'grouped collection accepts label and value methods options' do
119
120
  with_input_for @user, :tag_ids, :grouped_select,
120
- collection: { 'Authors' => ['Jose', 'Carlos'] },
121
+ collection: { Authors: %w[Jose Carlos] },
121
122
  group_method: :last,
122
123
  label_method: :upcase,
123
124
  value_method: :downcase
@@ -132,10 +133,10 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
132
133
 
133
134
  test 'grouped collection allows overriding label and value methods using a lambda' do
134
135
  with_input_for @user, :tag_ids, :grouped_select,
135
- collection: { 'Authors' => ['Jose', 'Carlos'] },
136
+ collection: { Authors: %w[Jose Carlos] },
136
137
  group_method: :last,
137
- label_method: lambda { |i| i.upcase },
138
- value_method: lambda { |i| i.downcase }
138
+ label_method: ->(i) { i.upcase },
139
+ value_method: ->(i) { i.downcase }
139
140
 
140
141
  assert_select 'select.grouped_select#user_tag_ids' do
141
142
  assert_select 'optgroup[label=Authors]' do
@@ -148,7 +149,7 @@ class GroupedCollectionSelectInputTest < ActionView::TestCase
148
149
  test 'grouped collection with associations' do
149
150
  tag_groups = [
150
151
  TagGroup.new(1, "Group of Tags", [Tag.new(1, "Tag 1"), Tag.new(2, "Tag 2")]),
151
- TagGroup.new(2, "Other group", [Tag.new(3, "Tag 3"), Tag.new(4,"Tag 4")])
152
+ TagGroup.new(2, "Other group", [Tag.new(3, "Tag 3"), Tag.new(4, "Tag 4")])
152
153
  ]
153
154
 
154
155
  with_input_for @user, :tag_ids, :grouped_select,
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -113,6 +114,9 @@ class NumericInputTest < ActionView::TestCase
113
114
 
114
115
  with_input_for @validating_user, :age, :integer
115
116
  assert_select 'input[step="1"]'
117
+
118
+ with_input_for @validating_user, :age, :integer, as: :decimal, input_html: { step: 0.5 }
119
+ assert_select 'input[step="0.5"]'
116
120
  end
117
121
 
118
122
  test 'numeric input does not generate placeholder by default' do
@@ -153,7 +157,7 @@ class NumericInputTest < ActionView::TestCase
153
157
  end
154
158
  end
155
159
 
156
- [:integer, :float, :decimal].each do |type|
160
+ %i[integer float decimal].each do |type|
157
161
  test "#{type} input infers min value from attributes with greater than or equal validation" do
158
162
  with_input_for @validating_user, :age, type
159
163
  assert_select 'input[min="18"]'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
  require 'test_helper'
3
4
 
@@ -5,14 +6,14 @@ class PriorityInputTest < ActionView::TestCase
5
6
  test 'input generates a country select field' do
6
7
  with_input_for @user, :country, :country
7
8
  assert_select 'select#user_country'
8
- assert_select 'select option[value=Brazil]', 'Brazil'
9
+ assert_select 'select option[value=BR]', 'Brazil'
9
10
  assert_no_select 'select option[value=""][disabled=disabled]'
10
11
  end
11
12
 
12
13
  test 'input generates a country select with SimpleForm default' do
13
14
  swap SimpleForm, country_priority: [ 'Brazil' ] do
14
15
  with_input_for @user, :country, :country
15
- assert_select 'select option[value=""][disabled=disabled]'
16
+ assert_select 'select option[value="---------------"][disabled=disabled]'
16
17
  end
17
18
  end
18
19
 
@@ -35,15 +36,15 @@ class PriorityInputTest < ActionView::TestCase
35
36
  assert_no_select 'select option[value=""]', /^$/
36
37
  end
37
38
 
38
- test 'priority input does not generate invalid required html attribute' do
39
+ test 'priority input does generate select element with required html attribute' do
39
40
  with_input_for @user, :country, :country
40
41
  assert_select 'select.required'
41
- assert_no_select 'select[required]'
42
+ assert_select 'select[required]'
42
43
  end
43
44
 
44
- test 'priority input does not generate invalid aria-required html attribute' do
45
+ test 'priority input does generate select element with aria-required html attribute' do
45
46
  with_input_for @user, :country, :country
46
47
  assert_select 'select.required'
47
- assert_no_select 'select[aria-required]'
48
+ assert_select 'select[aria-required]'
48
49
  end
49
50
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class ReadonlyTest < ActionView::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class RequiredTest < ActionView::TestCase
@@ -34,6 +35,38 @@ class RequiredTest < ActionView::TestCase
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]'
39
+ end
40
+ end
41
+
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
37
70
  end
38
71
  end
39
72
 
@@ -110,4 +143,16 @@ class RequiredTest < ActionView::TestCase
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