simple_form 3.0.4 → 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +199 -33
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +453 -128
  5. data/lib/generators/simple_form/install_generator.rb +4 -3
  6. data/lib/generators/simple_form/templates/README +3 -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 +47 -16
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +418 -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 +39 -6
  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 +220 -89
  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 +62 -16
  38. data/lib/simple_form/inputs/block_input.rb +2 -1
  39. data/lib/simple_form/inputs/boolean_input.rb +40 -16
  40. data/lib/simple_form/inputs/collection_check_boxes_input.rb +3 -2
  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/color_input.rb +14 -0
  45. data/lib/simple_form/inputs/date_time_input.rb +24 -9
  46. data/lib/simple_form/inputs/file_input.rb +5 -2
  47. data/lib/simple_form/inputs/grouped_collection_select_input.rb +16 -3
  48. data/lib/simple_form/inputs/hidden_input.rb +5 -2
  49. data/lib/simple_form/inputs/numeric_input.rb +6 -4
  50. data/lib/simple_form/inputs/password_input.rb +6 -3
  51. data/lib/simple_form/inputs/priority_input.rb +5 -6
  52. data/lib/simple_form/inputs/range_input.rb +2 -1
  53. data/lib/simple_form/inputs/rich_text_area_input.rb +12 -0
  54. data/lib/simple_form/inputs/string_input.rb +7 -4
  55. data/lib/simple_form/inputs/text_input.rb +6 -3
  56. data/lib/simple_form/inputs.rb +3 -0
  57. data/lib/simple_form/map_type.rb +1 -0
  58. data/lib/simple_form/railtie.rb +8 -0
  59. data/lib/simple_form/tags.rb +13 -2
  60. data/lib/simple_form/version.rb +2 -1
  61. data/lib/simple_form/wrappers/builder.rb +7 -6
  62. data/lib/simple_form/wrappers/leaf.rb +29 -0
  63. data/lib/simple_form/wrappers/many.rb +7 -6
  64. data/lib/simple_form/wrappers/root.rb +10 -3
  65. data/lib/simple_form/wrappers/single.rb +7 -4
  66. data/lib/simple_form/wrappers.rb +2 -0
  67. data/lib/simple_form.rb +137 -21
  68. data/test/action_view_extensions/builder_test.rb +64 -45
  69. data/test/action_view_extensions/form_helper_test.rb +36 -16
  70. data/test/components/custom_components_test.rb +62 -0
  71. data/test/components/label_test.rb +70 -41
  72. data/test/form_builder/association_test.rb +85 -37
  73. data/test/form_builder/button_test.rb +11 -10
  74. data/test/form_builder/error_notification_test.rb +2 -1
  75. data/test/form_builder/error_test.rb +146 -33
  76. data/test/form_builder/general_test.rb +183 -81
  77. data/test/form_builder/hint_test.rb +24 -18
  78. data/test/form_builder/input_field_test.rb +105 -75
  79. data/test/form_builder/label_test.rb +68 -13
  80. data/test/form_builder/wrapper_test.rb +197 -22
  81. data/test/generators/simple_form_generator_test.rb +8 -7
  82. data/test/inputs/boolean_input_test.rb +97 -6
  83. data/test/inputs/collection_check_boxes_input_test.rb +117 -25
  84. data/test/inputs/collection_radio_buttons_input_test.rb +176 -54
  85. data/test/inputs/collection_select_input_test.rb +189 -77
  86. data/test/inputs/color_input_test.rb +10 -0
  87. data/test/inputs/datetime_input_test.rb +121 -50
  88. data/test/inputs/disabled_test.rb +29 -15
  89. data/test/inputs/discovery_test.rb +79 -6
  90. data/test/inputs/file_input_test.rb +3 -2
  91. data/test/inputs/general_test.rb +23 -22
  92. data/test/inputs/grouped_collection_select_input_test.rb +54 -17
  93. data/test/inputs/hidden_input_test.rb +5 -4
  94. data/test/inputs/numeric_input_test.rb +48 -44
  95. data/test/inputs/priority_input_test.rb +17 -16
  96. data/test/inputs/readonly_test.rb +20 -19
  97. data/test/inputs/required_test.rb +58 -13
  98. data/test/inputs/rich_text_area_input_test.rb +15 -0
  99. data/test/inputs/string_input_test.rb +58 -36
  100. data/test/inputs/text_input_test.rb +20 -7
  101. data/test/simple_form_test.rb +9 -0
  102. data/test/support/discovery_inputs.rb +40 -2
  103. data/test/support/misc_helpers.rb +113 -5
  104. data/test/support/mock_controller.rb +7 -1
  105. data/test/support/models.rb +162 -39
  106. data/test/test_helper.rb +19 -4
  107. metadata +51 -43
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  # Tests for f.error and f.full_error
@@ -14,69 +15,70 @@ class ErrorTest < ActionView::TestCase
14
15
  end
15
16
  end
16
17
 
17
- def with_custom_error_for(object, *args)
18
- with_form_for(object, *args)
19
- end
20
-
21
- test 'error should not generate content for attribute without errors' do
18
+ test 'error does not generate content for attribute without errors' do
22
19
  with_error_for @user, :active
23
20
  assert_no_select 'span.error'
24
21
  end
25
22
 
26
- test 'error should not generate messages when object is not present' do
23
+ test 'error does not generate messages when object is not present' do
27
24
  with_error_for :project, :name
28
25
  assert_no_select 'span.error'
29
26
  end
30
27
 
31
- test "error should not generate messages when object doesn't respond to errors method" do
28
+ test "error does not generate messages when object doesn't respond to errors method" do
32
29
  @user.instance_eval { undef errors }
33
30
  with_error_for @user, :name
34
31
  assert_no_select 'span.error'
35
32
  end
36
33
 
37
- test 'error should generate messages for attribute with single error' do
34
+ test 'error generates messages for attribute with single error' do
38
35
  with_error_for @user, :name
39
- assert_select 'span.error', "can&#39;t be blank"
36
+ assert_select 'span.error', "cannot be blank"
37
+ end
38
+
39
+ test 'error generates messages with decorated object responsive to #to_model' do
40
+ with_error_for @decorated_user, :name
41
+ assert_select 'span.error', "cannot be blank"
40
42
  end
41
43
 
42
- test 'error should generate messages for attribute with one error when using first' do
44
+ test 'error generates messages for attribute with one error when using first' do
43
45
  swap SimpleForm, error_method: :first do
44
46
  with_error_for @user, :age
45
47
  assert_select 'span.error', 'is not a number'
46
48
  end
47
49
  end
48
50
 
49
- test 'error should generate messages for attribute with several errors when using to_sentence' do
51
+ test 'error generates messages for attribute with several errors when using to_sentence' do
50
52
  swap SimpleForm, error_method: :to_sentence do
51
53
  with_error_for @user, :age
52
54
  assert_select 'span.error', 'is not a number and must be greater than 18'
53
55
  end
54
56
  end
55
57
 
56
- test 'error should be able to pass html options' do
58
+ test 'error is able to pass html options' do
57
59
  with_error_for @user, :name, id: 'error', class: 'yay'
58
60
  assert_select 'span#error.error.yay'
59
61
  end
60
62
 
61
- test 'error should not modify the options hash' do
63
+ test 'error does not modify the options hash' do
62
64
  options = { id: 'error', class: 'yay' }
63
65
  with_error_for @user, :name, options
64
66
  assert_select 'span#error.error.yay'
65
67
  assert_equal({ id: 'error', class: 'yay' }, options)
66
68
  end
67
69
 
68
- test 'error should find errors on attribute and association' do
70
+ test 'error finds errors on attribute and association' do
69
71
  with_error_for @user, :company_id, as: :select,
70
72
  error_method: :to_sentence, reflection: Association.new(Company, :company, {})
71
73
  assert_select 'span.error', 'must be valid and company must be present'
72
74
  end
73
75
 
74
- test 'error should generate an error tag with a clean HTML' do
76
+ test 'error generates an error tag with a clean HTML' do
75
77
  with_error_for @user, :name
76
78
  assert_no_select 'span.error[error_html]'
77
79
  end
78
80
 
79
- test 'error should generate an error tag with a clean HTML when errors options are present' do
81
+ test 'error generates an error tag with a clean HTML when errors options are present' do
80
82
  with_error_for @user, :name, error_tag: :p, error_prefix: 'Name', error_method: :first
81
83
  assert_no_select 'p.error[error_html]'
82
84
  assert_no_select 'p.error[error_tag]'
@@ -84,13 +86,13 @@ class ErrorTest < ActionView::TestCase
84
86
  assert_no_select 'p.error[error_method]'
85
87
  end
86
88
 
87
- test 'error should escape error prefix text' do
89
+ test 'error escapes error prefix text' do
88
90
  with_error_for @user, :name, error_prefix: '<b>Name</b>'
89
- assert_select 'span.error', "&lt;b&gt;Name&lt;/b&gt; can&#39;t be blank"
91
+ assert_no_select 'span.error b'
90
92
  end
91
93
 
92
94
  test 'error escapes error text' do
93
- @user.errors.merge!(action: ['must not contain <b>markup</b>'])
95
+ @user.errors.add(:action, 'must not contain <b>markup</b>')
94
96
 
95
97
  with_error_for @user, :action
96
98
 
@@ -98,60 +100,145 @@ class ErrorTest < ActionView::TestCase
98
100
  assert_no_select 'span.error b', 'markup'
99
101
  end
100
102
 
101
- test 'error should generate an error message with raw HTML tags' do
103
+ test 'error generates an error message with raw HTML tags' do
102
104
  with_error_for @user, :name, error_prefix: '<b>Name</b>'.html_safe
103
- assert_select 'span.error', "Name can&#39;t be blank"
105
+ assert_select 'span.error', "Name cannot be blank"
104
106
  assert_select 'span.error b', "Name"
105
107
  end
106
108
 
109
+ test 'error adds aria-invalid attribute to inputs' do
110
+ with_form_for @user, :name, error: true
111
+ assert_select "input#user_name[name='user[name]'][aria-invalid='true']"
112
+
113
+ with_form_for @user, :name, as: :text, error: true
114
+ assert_select "textarea#user_name[name='user[name]'][aria-invalid='true']"
115
+
116
+ @user.errors.add(:active, 'must select one')
117
+ with_form_for @user, :active, as: :radio_buttons
118
+ assert_select "input#user_active_true[type=radio][name='user[active]'][aria-invalid='true']"
119
+ assert_select "input#user_active_false[type=radio][name='user[active]'][aria-invalid='true']"
120
+
121
+ with_form_for @user, :active, as: :check_boxes
122
+ assert_select "input#user_active_true[type=checkbox][aria-invalid='true']"
123
+ assert_select "input#user_active_false[type=checkbox][aria-invalid='true']"
124
+
125
+ with_form_for @user, :company_id, as: :select, error: true
126
+ assert_select "select#user_company_id[aria-invalid='true']"
127
+
128
+ @user.errors.add(:password, 'must not be blank')
129
+ with_form_for @user, :password
130
+ assert_select "input#user_password[type=password][aria-invalid='true']"
131
+ end
132
+
107
133
  # FULL ERRORS
108
134
 
109
- test 'full error should generate an full error tag for the attribute' do
135
+ test 'full error generates a full error tag for the attribute' do
110
136
  with_full_error_for @user, :name
111
- assert_select 'span.error', "Super User Name! can&#39;t be blank"
137
+ assert_select 'span.error', "Super User Name! cannot be blank"
112
138
  end
113
139
 
114
- test 'full error should generate an full error tag with a clean HTML' do
140
+ test 'full error generates a full error tag with a clean HTML' do
115
141
  with_full_error_for @user, :name
116
142
  assert_no_select 'span.error[error_html]'
117
143
  end
118
144
 
119
- test 'full error should allow passing options to full error tag' do
145
+ test 'full error allows passing options to full error tag' do
120
146
  with_full_error_for @user, :name, id: 'name_error', error_prefix: "Your name"
121
- assert_select 'span.error#name_error', "Your name can&#39;t be blank"
147
+ assert_select 'span.error#name_error', "Your name cannot be blank"
122
148
  end
123
149
 
124
- test 'full error should not modify the options hash' do
150
+ test 'full error does not modify the options hash' do
125
151
  options = { id: 'name_error' }
126
152
  with_full_error_for @user, :name, options
127
- assert_select 'span.error#name_error', "Super User Name! can&#39;t be blank"
153
+ assert_select 'span.error#name_error', "Super User Name! cannot be blank"
128
154
  assert_equal({ id: 'name_error' }, options)
129
155
  end
130
156
 
157
+ test 'full error escapes error text' do
158
+ @user.errors.add(:action, 'must not contain <b>markup</b>')
159
+
160
+ with_full_error_for @user, :action
161
+
162
+ assert_select 'span.error'
163
+ assert_no_select 'span.error b', 'markup'
164
+ end
165
+
131
166
  # CUSTOM WRAPPERS
132
167
 
133
168
  test 'error with custom wrappers works' do
134
169
  swap_wrapper do
135
170
  with_error_for @user, :name
136
- assert_select 'span.omg_error', "can&#39;t be blank"
171
+ assert_select 'span.omg_error', "cannot be blank"
172
+ end
173
+ end
174
+
175
+ # FULL_ERROR_WRAPPER
176
+
177
+ test 'full error finds errors on association' do
178
+ swap_wrapper :default, custom_wrapper_with_full_error do
179
+ with_form_for @user, :company_id, as: :select
180
+ assert_select 'span.error', 'Company must be valid'
181
+ end
182
+ end
183
+
184
+ test 'full error finds errors on association with reflection' do
185
+ swap_wrapper :default, custom_wrapper_with_full_error do
186
+ with_form_for @user, :company_id, as: :select,
187
+ reflection: Association.new(Company, :company, {})
188
+ assert_select 'span.error', 'Company must be valid'
189
+ end
190
+ end
191
+
192
+ test 'full error can be disabled' do
193
+ swap_wrapper :default, custom_wrapper_with_full_error do
194
+ with_form_for @user, :company_id, as: :select, full_error: false
195
+ assert_no_select 'span.error'
196
+ end
197
+ end
198
+
199
+ test 'full error can be disabled setting error to false' do
200
+ swap_wrapper :default, custom_wrapper_with_full_error do
201
+ with_form_for @user, :company_id, as: :select, error: false
202
+ assert_no_select 'span.error'
137
203
  end
138
204
  end
139
205
 
140
206
  # CUSTOM ERRORS
141
207
 
142
208
  test 'input with custom error works' do
143
- with_custom_error_for(@user, :name, error: "Super User Name! can't be blank")
209
+ error_text = "Super User Name! cannot be blank"
210
+ with_form_for @user, :name, error: error_text
144
211
 
145
- assert_select 'span.error', "Super User Name! can&#39;t be blank"
212
+ assert_select 'span.error', error_text
213
+ end
214
+
215
+ test 'input with error option as true does not use custom error' do
216
+ with_form_for @user, :name, error: true
217
+
218
+ assert_select 'span.error', "cannot be blank"
146
219
  end
147
220
 
148
221
  test 'input with custom error does not generate the error if there is no error on the attribute' do
149
- error_text = "Super User Active! can't be blank"
150
- with_form_for @user, :active, error: error_text
222
+ with_form_for @user, :active, error: "Super User Active! cannot be blank"
151
223
 
152
224
  assert_no_select 'span.error'
153
225
  end
154
226
 
227
+ test 'input with custom error works when form does not use a model' do
228
+ with_form_for :user, :active, error: "Super User Active! cannot be blank"
229
+
230
+ assert_select 'span.error'
231
+ end
232
+
233
+ test 'input with custom error works when using full_error component' do
234
+ swap_wrapper :default, custom_wrapper_with_full_error do
235
+ error_text = "Super User Name! cannot be blank"
236
+ with_form_for @user, :name, error: error_text
237
+
238
+ assert_select 'span.error', error_text
239
+ end
240
+ end
241
+
155
242
  test 'input with custom error escapes the error text' do
156
243
  with_form_for @user, :name, error: 'error must not contain <b>markup</b>'
157
244
 
@@ -165,4 +252,30 @@ class ErrorTest < ActionView::TestCase
165
252
  assert_select 'span.error'
166
253
  assert_select 'span.error b', 'markup'
167
254
  end
255
+
256
+ test 'input with custom error escapes the error text using full_error component' do
257
+ swap_wrapper :default, custom_wrapper_with_full_error do
258
+ with_form_for @user, :name, error: 'error must not contain <b>markup</b>'
259
+
260
+ assert_select 'span.error'
261
+ assert_no_select 'span.error b', 'markup'
262
+ end
263
+ end
264
+
265
+ test 'input with custom error does not escape the error text if it is safe using full_error component' do
266
+ swap_wrapper :default, custom_wrapper_with_full_error do
267
+ with_form_for @user, :name, error: 'error must contain <b>markup</b>'.html_safe
268
+
269
+ assert_select 'span.error'
270
+ assert_select 'span.error b', 'markup'
271
+ end
272
+ end
273
+
274
+ test 'input with custom error when using full_error component does not generate the error if there is no error on the attribute' do
275
+ swap_wrapper :default, custom_wrapper_with_full_error do
276
+ with_form_for @user, :active, error: "Super User Active! can't be blank"
277
+
278
+ assert_no_select 'span.error'
279
+ end
280
+ end
168
281
  end