simple_form 1.2.2 → 1.3.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.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

Files changed (36) hide show
  1. data/README.rdoc +80 -14
  2. data/lib/generators/simple_form/templates/_form.html.erb +1 -11
  3. data/lib/generators/simple_form/templates/simple_form.rb +31 -6
  4. data/lib/simple_form.rb +38 -2
  5. data/lib/simple_form/action_view_extensions/builder.rb +53 -20
  6. data/lib/simple_form/components.rb +6 -5
  7. data/lib/simple_form/components/errors.rb +4 -6
  8. data/lib/simple_form/components/hints.rb +2 -2
  9. data/lib/simple_form/components/labels.rb +3 -5
  10. data/lib/simple_form/components/placeholders.rb +22 -0
  11. data/lib/simple_form/components/wrapper.rb +7 -0
  12. data/lib/simple_form/error_notification.rb +4 -6
  13. data/lib/simple_form/form_builder.rb +61 -55
  14. data/lib/simple_form/has_errors.rb +14 -0
  15. data/lib/simple_form/inputs/base.rb +45 -17
  16. data/lib/simple_form/inputs/block_input.rb +3 -2
  17. data/lib/simple_form/inputs/collection_input.rb +42 -17
  18. data/lib/simple_form/inputs/date_time_input.rb +3 -1
  19. data/lib/simple_form/inputs/hidden_input.rb +11 -2
  20. data/lib/simple_form/inputs/mapping_input.rb +16 -3
  21. data/lib/simple_form/inputs/numeric_input.rb +45 -8
  22. data/lib/simple_form/inputs/string_input.rb +13 -9
  23. data/lib/simple_form/map_type.rb +4 -4
  24. data/lib/simple_form/version.rb +1 -1
  25. data/test/action_view_extensions/builder_test.rb +155 -51
  26. data/test/components/error_test.rb +10 -8
  27. data/test/components/hint_test.rb +4 -8
  28. data/test/components/label_test.rb +22 -9
  29. data/test/components/wrapper_test.rb +16 -7
  30. data/test/error_notification_test.rb +4 -3
  31. data/test/form_builder_test.rb +81 -34
  32. data/test/inputs_test.rb +242 -3
  33. data/test/support/misc_helpers.rb +6 -4
  34. data/test/support/models.rb +26 -3
  35. data/test/test_helper.rb +13 -5
  36. metadata +25 -8
@@ -3,14 +3,10 @@ require 'test_helper'
3
3
  class ErrorTest < ActionView::TestCase
4
4
 
5
5
  def with_error_for(object, attribute_name, type, options={}, &block)
6
- concat(simple_form_for(object) do |f|
7
- f.attribute_name = attribute_name
8
- f.reflection = Association.new(Company, :company, {}) if options.delete(:setup_association)
9
- f.input_type = type
10
- f.options = options
11
-
12
- concat(SimpleForm::Inputs::Base.new(f).error.to_s)
13
- end)
6
+ with_concat_form_for(object) do |f|
7
+ options[:reflection] = Association.new(Company, :company, {}) if options.delete(:setup_association)
8
+ SimpleForm::Inputs::Base.new(f, attribute_name, nil, type, options).error.to_s
9
+ end
14
10
  end
15
11
 
16
12
  test 'error should not generate content for attribute without errors' do
@@ -23,6 +19,12 @@ class ErrorTest < ActionView::TestCase
23
19
  assert_no_select 'span.error'
24
20
  end
25
21
 
22
+ test "error should not generate messages when object doesn't respond to errors method" do
23
+ @user.instance_eval { undef errors }
24
+ with_error_for @user, :name, :string
25
+ assert_no_select 'span.error'
26
+ end
27
+
26
28
  test 'error should generate messages for attribute with single error' do
27
29
  with_error_for @user, :name, :string
28
30
  assert_select 'span.error', "can't be blank"
@@ -3,14 +3,10 @@ require 'test_helper'
3
3
  class HintTest < ActionView::TestCase
4
4
 
5
5
  def with_hint_for(object, attribute_name, type, options={}, &block)
6
- concat(simple_form_for(object) do |f|
7
- f.attribute_name = attribute_name
8
- f.reflection = Association.new(Company, :company, {}) if options.delete(:setup_association)
9
- f.input_type = type
10
- f.options = options
11
-
12
- concat(SimpleForm::Inputs::Base.new(f).hint.to_s)
13
- end)
6
+ with_concat_form_for(object) do |f|
7
+ options[:reflection] = Association.new(Company, :company, {}) if options.delete(:setup_association)
8
+ SimpleForm::Inputs::Base.new(f, attribute_name, nil, type, options).hint.to_s
9
+ end
14
10
  end
15
11
 
16
12
  test 'hint should not be generated by default' do
@@ -2,20 +2,15 @@
2
2
  require 'test_helper'
3
3
 
4
4
  class LabelTest < ActionView::TestCase
5
-
6
5
  setup do
7
6
  SimpleForm::Inputs::Base.reset_i18n_cache :translate_required_html
8
7
  end
9
8
 
10
9
  def with_label_for(object, attribute_name, type, options={})
11
- concat(simple_form_for(object) do |f|
12
- f.attribute_name = attribute_name
13
- f.reflection = Association.new(Company, :company, {}) if options.delete(:setup_association)
14
- f.input_type = type
15
- f.options = options
16
-
17
- concat(SimpleForm::Inputs::Base.new(f).label)
18
- end)
10
+ with_concat_form_for(object) do |f|
11
+ options[:reflection] = Association.new(Company, :company, {}) if options.delete(:setup_association)
12
+ SimpleForm::Inputs::Base.new(f, attribute_name, nil, type, options).label
13
+ end
19
14
  end
20
15
 
21
16
  test 'label should generate a default humanized description' do
@@ -58,6 +53,15 @@ class LabelTest < ActionView::TestCase
58
53
  end
59
54
  end
60
55
 
56
+ test 'label should not explode while looking for i18n translation when action is not set' do
57
+ def @controller.action_name; nil; end
58
+
59
+ assert_nothing_raised do
60
+ with_label_for @user, :description, :text
61
+ end
62
+ assert_select 'label[for=user_description]'
63
+ end
64
+
61
65
  test 'label should use i18n based on model and attribute to lookup translation' do
62
66
  store_translations(:en, :simple_form => { :labels => { :user => {
63
67
  :description => 'Descrição'
@@ -74,6 +78,15 @@ class LabelTest < ActionView::TestCase
74
78
  end
75
79
  end
76
80
 
81
+ test 'input should not use i18n label if translate is false' do
82
+ swap SimpleForm, :translate => false do
83
+ store_translations(:en, :simple_form => { :labels => { :age => 'Idade' } } ) do
84
+ with_label_for @user, :age, :integer
85
+ assert_select 'label[for=user_age]', /Age/
86
+ end
87
+ end
88
+ end
89
+
77
90
  test 'label should use i18n with lookup for association name' do
78
91
  store_translations(:en, :simple_form => { :labels => {
79
92
  :user => { :company => 'My company!' }
@@ -1,17 +1,16 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class WrapperTest < ActionView::TestCase
4
- def with_error_for(object, attribute_name, options={}, &block)
5
- concat(simple_form_for(object) do |f|
6
- f.options = options
4
+ def with_error_for(object, attribute_name, &block)
5
+ with_concat_form_for(object) do |f|
7
6
  f.input attribute_name
8
- end)
7
+ end
9
8
  end
10
9
 
11
10
  def with_form_for(object, *args, &block)
12
- concat(simple_form_for(object) do |f|
13
- concat f.input(*args, &block)
14
- end)
11
+ with_concat_form_for(object) do |f|
12
+ f.input(*args, &block)
13
+ end
15
14
  end
16
15
 
17
16
  test 'wrapper should not have error class for attribute without errors' do
@@ -51,4 +50,14 @@ class WrapperTest < ActionView::TestCase
51
50
  assert_no_select 'div.input'
52
51
  end
53
52
  end
53
+
54
+ test 'wrapper should not have disabled class by default' do
55
+ with_form_for @user, :active
56
+ assert_no_select 'div.disabled'
57
+ end
58
+
59
+ test 'wrapper should add disabled class when the input is disabled' do
60
+ with_form_for @user, :active, :disabled => true
61
+ assert_select 'div.disabled'
62
+ end
54
63
  end
@@ -1,11 +1,12 @@
1
+ # encoding: UTF-8
1
2
  require 'test_helper'
2
3
 
3
4
  class ErrorNotificationTest < ActionView::TestCase
4
5
 
5
6
  def with_error_notification_for(object, options={}, &block)
6
- concat(simple_form_for(object) do |f|
7
- concat(f.error_notification(options))
8
- end)
7
+ with_concat_form_for(object) do |f|
8
+ f.error_notification(options)
9
+ end
9
10
  end
10
11
 
11
12
  test 'error notification is not generated when the object has no error' do
@@ -4,39 +4,39 @@ require 'test_helper'
4
4
  class FormBuilderTest < ActionView::TestCase
5
5
 
6
6
  def with_form_for(object, *args, &block)
7
- concat(simple_form_for(object) do |f|
8
- concat f.input(*args, &block)
9
- end)
7
+ with_concat_form_for(object) do |f|
8
+ f.input(*args, &block)
9
+ end
10
10
  end
11
11
 
12
12
  def with_button_for(object, *args)
13
- concat(simple_form_for(object) do |f|
14
- concat f.button(*args)
15
- end)
13
+ with_concat_form_for(object) do |f|
14
+ f.button(*args)
15
+ end
16
16
  end
17
17
 
18
18
  def with_error_for(object, *args)
19
- concat(simple_form_for(object) do |f|
20
- concat f.error(*args)
21
- end)
19
+ with_concat_form_for(object) do |f|
20
+ f.error(*args)
21
+ end
22
22
  end
23
23
 
24
24
  def with_hint_for(object, *args)
25
- concat(simple_form_for(object) do |f|
26
- concat f.hint(*args)
27
- end)
25
+ with_concat_form_for(object) do |f|
26
+ f.hint(*args)
27
+ end
28
28
  end
29
29
 
30
30
  def with_label_for(object, *args)
31
- concat(simple_form_for(object) do |f|
32
- concat f.label(*args)
33
- end)
31
+ with_concat_form_for(object) do |f|
32
+ f.label(*args)
33
+ end
34
34
  end
35
35
 
36
36
  def with_association_for(object, *args)
37
- concat(simple_form_for(object) do |f|
38
- concat f.association(*args)
39
- end)
37
+ with_concat_form_for(object) do |f|
38
+ f.association(*args)
39
+ end
40
40
  end
41
41
 
42
42
  # All
@@ -56,12 +56,28 @@ class FormBuilderTest < ActionView::TestCase
56
56
 
57
57
  test 'builder input should allow a block to configure input' do
58
58
  with_form_for @user, :name do
59
- concat text_field_tag :foo, :bar, :id => :cool
59
+ text_field_tag :foo, :bar, :id => :cool
60
60
  end
61
61
  assert_no_select 'input.string'
62
62
  assert_select 'input#cool'
63
63
  end
64
64
 
65
+ test 'builder should allow adding custom input mappings for default input types' do
66
+ swap SimpleForm, :input_mappings => { /count$/ => :integer } do
67
+ with_form_for @user, :post_count
68
+ assert_no_select 'form input#user_post_count.string'
69
+ assert_select 'form input#user_post_count.numeric.integer'
70
+ end
71
+ end
72
+
73
+ test 'builder uses the first matching custom input map when more than one match' do
74
+ swap SimpleForm, :input_mappings => { /count$/ => :integer, /^post_/ => :password } do
75
+ with_form_for @user, :post_count
76
+ assert_no_select 'form input#user_post_count.password'
77
+ assert_select 'form input#user_post_count.numeric.integer'
78
+ end
79
+ end
80
+
65
81
  # INPUT TYPES
66
82
  test 'builder should generate text fields for string columns' do
67
83
  with_form_for @user, :name
@@ -108,6 +124,11 @@ class FormBuilderTest < ActionView::TestCase
108
124
  assert_select 'form input#user_email.string.email'
109
125
  end
110
126
 
127
+ test 'builder should generate tel fields for columns that matches phone' do
128
+ with_form_for @user, :phone_number
129
+ assert_select 'form input#user_phone_number.string.tel'
130
+ end
131
+
111
132
  test 'builder should generate url fields for columns that matches url' do
112
133
  with_form_for @user, :url
113
134
  assert_select 'form input#user_url.string.url'
@@ -230,10 +251,19 @@ class FormBuilderTest < ActionView::TestCase
230
251
  assert_select 'span.error#cool', "can't be blank"
231
252
  end
232
253
 
254
+ test 'placeholder should not be generated when set to false' do
255
+ store_translations(:en, :simple_form => { :placeholders => { :user => {
256
+ :name => 'Name goes here'
257
+ } } }) do
258
+ with_form_for @user, :name, :placeholder => false
259
+ assert_no_select 'input[placeholder]'
260
+ end
261
+ end
262
+
233
263
  # REQUIRED AND PRESENCE VALIDATION
234
264
  test 'builder input should obtain required from ActiveModel::Validations when it is included' do
235
265
  with_form_for @validating_user, :name
236
- assert_select 'input.required#validating_user_name'
266
+ assert_select 'input.required[required]#validating_user_name'
237
267
  with_form_for @validating_user, :status
238
268
  assert_select 'input.optional#validating_user_status'
239
269
  end
@@ -242,24 +272,26 @@ class FormBuilderTest < ActionView::TestCase
242
272
  with_form_for @validating_user, :name, :required => false
243
273
  assert_select 'input.optional#validating_user_name'
244
274
  with_form_for @validating_user, :status, :required => true
245
- assert_select 'input.required#validating_user_status'
275
+ assert_select 'input.required[required]#validating_user_status'
246
276
  end
247
277
 
248
278
  test 'builder input should be required by default when ActiveModel::Validations is not included' do
249
279
  with_form_for @user, :name
250
- assert_select 'input.required#user_name'
280
+ assert_select 'input.required[required]#user_name'
251
281
  end
252
282
 
253
283
  test 'builder input should not be required by default when ActiveModel::Validations is not included if option is set to false' do
254
284
  swap SimpleForm, :required_by_default => false do
255
285
  with_form_for @user, :name
256
286
  assert_select 'input.optional#user_name'
287
+ assert_no_select 'input[required]'
257
288
  end
258
289
  end
259
290
 
260
291
  test 'builder input should allow disabling required when ActiveModel::Validations is not included' do
261
292
  with_form_for @user, :name, :required => false
262
293
  assert_no_select 'input.required'
294
+ assert_no_select 'input[required]'
263
295
  assert_select 'input.optional#user_name'
264
296
  end
265
297
 
@@ -290,16 +322,16 @@ class FormBuilderTest < ActionView::TestCase
290
322
  end
291
323
 
292
324
  test 'builder allows wrapper tag to be given on demand' do
293
- concat(simple_form_for(@user) do |f|
294
- concat f.input :name, :wrapper_tag => :b
295
- end)
325
+ with_concat_form_for(@user) do |f|
326
+ f.input :name, :wrapper_tag => :b
327
+ end
296
328
  assert_select 'form b.required.string'
297
329
  end
298
330
 
299
331
  test 'builder allows wrapper class to be given on demand' do
300
- concat(simple_form_for(@user) do |f|
301
- concat f.input :name, :wrapper_class => :wrapper
302
- end)
332
+ with_concat_form_for(@user) do |f|
333
+ f.input :name, :wrapper_class => :wrapper
334
+ end
303
335
  assert_select 'form div.wrapper.required.string'
304
336
  end
305
337
 
@@ -353,9 +385,9 @@ class FormBuilderTest < ActionView::TestCase
353
385
  end
354
386
 
355
387
  test 'builder should generate a hint component tag for the given text' do
356
- with_hint_for @user, 'Hello World!'
357
- assert_select 'span.hint', 'Hello World!'
358
- end
388
+ with_hint_for @user, 'Hello World!'
389
+ assert_select 'span.hint', 'Hello World!'
390
+ end
359
391
 
360
392
  test 'builder should allow passing options to hint tag' do
361
393
  with_hint_for @user, :name, :hint => 'Hello World!', :id => 'name_hint'
@@ -370,7 +402,7 @@ class FormBuilderTest < ActionView::TestCase
370
402
 
371
403
  test 'builder should add a required class to label if the attribute is required' do
372
404
  with_label_for @validating_user, :name
373
- assert_select 'label.string[for=validating_user_name]', /Name/
405
+ assert_select 'label.string.required[for=validating_user_name]', /Name/
374
406
  end
375
407
 
376
408
  test 'builder should allow passing options to label tag' do
@@ -394,13 +426,13 @@ class FormBuilderTest < ActionView::TestCase
394
426
  # BUTTONS
395
427
  test 'builder should create buttons' do
396
428
  with_button_for :post, :submit
397
- assert_select 'form input[type=submit][value=Save Post]'
429
+ assert_select 'form input.button[type=submit][value=Save Post]'
398
430
  end
399
431
 
400
432
  test 'builder should create buttons for records' do
401
433
  @user.new_record!
402
434
  with_button_for @user, :submit
403
- assert_select 'form input[type=submit][value=Create User]'
435
+ assert_select 'form input.button[type=submit][value=Create User]'
404
436
  end
405
437
 
406
438
  # ASSOCIATIONS
@@ -429,6 +461,13 @@ class FormBuilderTest < ActionView::TestCase
429
461
  assert_equal 3, calls
430
462
  end
431
463
 
464
+ test 'builder association mark input as required based both association and attribute' do
465
+ swap SimpleForm, :required_by_default => false do
466
+ with_association_for @validating_user, :company, :collection => []
467
+ assert_select 'label.required'
468
+ end
469
+ end
470
+
432
471
  # ASSOCIATIONS - BELONGS TO
433
472
  test 'builder creates a select for belongs_to associations' do
434
473
  with_association_for @user, :company
@@ -515,4 +554,12 @@ class FormBuilderTest < ActionView::TestCase
515
554
  assert_select 'form input[type=checkbox][value=2][checked=checked]'
516
555
  assert_no_select 'form input[type=checkbox][value=3][checked=checked]'
517
556
  end
557
+
558
+ test 'builder with collection support giving collection and item wrapper tags' do
559
+ with_association_for @user, :tags, :as => :check_boxes,
560
+ :collection_wrapper_tag => :ul, :item_wrapper_tag => :li
561
+
562
+ assert_select 'form ul', :count => 1
563
+ assert_select 'form ul li', :count => 3
564
+ end
518
565
  end
data/test/inputs_test.rb CHANGED
@@ -8,9 +8,9 @@ class InputTest < ActionView::TestCase
8
8
  end
9
9
 
10
10
  def with_input_for(object, attribute_name, type, options={})
11
- concat(simple_form_for(object) do |f|
12
- concat f.input(attribute_name, options.merge(:as => type))
13
- end)
11
+ with_concat_form_for(object) do |f|
12
+ f.input(attribute_name, options.merge(:as => type))
13
+ end
14
14
  end
15
15
 
16
16
  # ALL
@@ -27,6 +27,67 @@ class InputTest < ActionView::TestCase
27
27
  assert_select 'select.datetime'
28
28
  end
29
29
 
30
+ test 'input should generate disabled elements based on the disabled option' do
31
+ with_input_for @user, :name, :string, :disabled => true
32
+ assert_select 'input.string[disabled]'
33
+ with_input_for @user, :description, :text, :disabled => true
34
+ assert_select 'textarea.text[disabled]'
35
+ with_input_for @user, :age, :integer, :disabled => true
36
+ assert_select 'input.integer[disabled]'
37
+ with_input_for @user, :born_at, :date, :disabled => true
38
+ assert_select 'select.date[disabled]'
39
+ with_input_for @user, :created_at, :datetime, :disabled => true
40
+ assert_select 'select.datetime[disabled]'
41
+
42
+ with_input_for @user, :name, :string, :disabled => false
43
+ assert_select 'input.string:not([disabled])'
44
+ with_input_for @user, :description, :text, :disabled => false
45
+ assert_select 'textarea.text:not([disabled])'
46
+ with_input_for @user, :age, :integer, :disabled => false
47
+ assert_select 'input.integer:not([disabled])'
48
+ with_input_for @user, :born_at, :date, :disabled => false
49
+ assert_select 'select.date:not([disabled])'
50
+ with_input_for @user, :created_at, :datetime, :disabled => false
51
+ assert_select 'select.datetime:not([disabled])'
52
+
53
+ with_input_for @user, :name, :string
54
+ assert_select 'input.string:not([disabled])'
55
+ with_input_for @user, :description, :text
56
+ assert_select 'textarea.text:not([disabled])'
57
+ with_input_for @user, :age, :integer
58
+ assert_select 'input.integer:not([disabled])'
59
+ with_input_for @user, :born_at, :date
60
+ assert_select 'select.date:not([disabled])'
61
+ with_input_for @user, :created_at, :datetime
62
+ assert_select 'select.datetime:not([disabled])'
63
+ end
64
+
65
+ test 'input should render components according to an optional :components option' do
66
+ with_input_for @user, :name, :string, :components => [:input, :label]
67
+ assert_select 'input + label'
68
+
69
+ with_input_for @user, :age, :integer, :components => [:input, :label]
70
+ assert_select 'input + label'
71
+
72
+ with_input_for @user, :active, :boolean, :components => [:label, :input]
73
+ assert_select 'label + input'
74
+
75
+ with_input_for @user, :description, :text, :components => [:input, :label]
76
+ assert_select 'textarea + label'
77
+
78
+ with_input_for @user, :password, :password, :components => [:input, :label]
79
+ assert_select 'input + label'
80
+
81
+ with_input_for @user, :name, :file, :components => [:input, :label]
82
+ assert_select 'input + label'
83
+
84
+ with_input_for @user, :country, :country, :components => [:input, :label]
85
+ assert_select 'select + label'
86
+
87
+ with_input_for @user, :time_zone, :time_zone, :components => [:input, :label]
88
+ assert_select 'select + label'
89
+ end
90
+
30
91
  # StringInput
31
92
  test 'input should map text field to string attribute' do
32
93
  with_input_for @user, :name, :string
@@ -48,6 +109,32 @@ class InputTest < ActionView::TestCase
48
109
  assert_select 'input.string[size=50]'
49
110
  end
50
111
 
112
+ test 'input should not generate placeholder by default' do
113
+ with_input_for @user, :name, :string
114
+ assert_no_select 'input[placeholder]'
115
+ end
116
+
117
+ test 'input should accept the placeholder option' do
118
+ with_input_for @user, :name, :string, :placeholder => 'Put in some text'
119
+ assert_select 'input.string[placeholder=Put in some text]'
120
+ end
121
+
122
+ test 'input should use i18n to translate placeholder text' do
123
+ store_translations(:en, :simple_form => { :placeholders => { :user => {
124
+ :name => 'Name goes here'
125
+ } } }) do
126
+ with_input_for @user, :name, :string
127
+ assert_select 'input.string[placeholder=Name goes here]'
128
+ end
129
+ end
130
+
131
+ [:email, :url, :search, :tel].each do |type|
132
+ test "input should allow type #{type}" do
133
+ with_input_for @user, :name, type
134
+ assert_select "input.string.#{type}"
135
+ end
136
+ end
137
+
51
138
  # NumericInput
52
139
  test 'input should generate an integer text field for integer attributes ' do
53
140
  with_input_for @user, :age, :integer
@@ -64,6 +151,71 @@ class InputTest < ActionView::TestCase
64
151
  assert_select 'input[type=number].decimal#user_age'
65
152
  end
66
153
 
154
+ test 'input should not generate min attribute by default' do
155
+ with_input_for @user, :age, :integer
156
+ assert_no_select 'input[min]'
157
+ end
158
+
159
+ test 'input should not generate max attribute by default' do
160
+ with_input_for @user, :age, :integer
161
+ assert_no_select 'input[max]'
162
+ end
163
+
164
+ test 'input should infer min value from integer attributes with greater than validation' do
165
+ with_input_for @other_validating_user, :age, :float
166
+ assert_no_select 'input[min]'
167
+
168
+ with_input_for @other_validating_user, :age, :integer
169
+ assert_select 'input[min=18]'
170
+ end
171
+
172
+ test 'input should infer max value from attributes with less than validation' do
173
+ with_input_for @other_validating_user, :age, :float
174
+ assert_no_select 'input[max]'
175
+
176
+ with_input_for @other_validating_user, :age, :integer
177
+ assert_select 'input[max=99]'
178
+ end
179
+
180
+ test 'input should infer step value only from integer attribute' do
181
+ with_input_for @validating_user, :age, :float
182
+ assert_no_select 'input[step]'
183
+
184
+ with_input_for @validating_user, :age, :integer
185
+ assert_select 'input[step=1]'
186
+ end
187
+
188
+ test 'numeric input should not generate placeholder by default' do
189
+ with_input_for @user, :age, :integer
190
+ assert_no_select 'input[placeholder]'
191
+ end
192
+
193
+ test 'numeric input should accept the placeholder option' do
194
+ with_input_for @user, :age, :integer, :placeholder => 'Put in your age'
195
+ assert_select 'input.integer[placeholder=Put in your age]'
196
+ end
197
+
198
+ test 'numeric input should use i18n to translate placeholder text' do
199
+ store_translations(:en, :simple_form => { :placeholders => { :user => {
200
+ :age => 'Age goes here'
201
+ } } }) do
202
+ with_input_for @user, :age, :integer
203
+ assert_select 'input.integer[placeholder=Age goes here]'
204
+ end
205
+ end
206
+
207
+ [:integer, :float, :decimal].each do |type|
208
+ test "#{type} input should infer min value from attributes with greater than or equal validation" do
209
+ with_input_for @validating_user, :age, type
210
+ assert_select 'input[min=18]'
211
+ end
212
+
213
+ test "#{type} input should infer the max value from attributes with less than or equal to validation" do
214
+ with_input_for @validating_user, :age, type
215
+ assert_select 'input[max=99]'
216
+ end
217
+ end
218
+
67
219
  # BooleanInput
68
220
  test 'input should generate a checkbox by default for boolean attributes' do
69
221
  with_input_for @user, :active, :boolean
@@ -77,16 +229,39 @@ class InputTest < ActionView::TestCase
77
229
  assert_select 'textarea.text#user_description'
78
230
  end
79
231
 
232
+ test 'input should generate a text area for text attributes that accept placeholder' do
233
+ with_input_for @user, :description, :text, :placeholder => 'Put in some text'
234
+ assert_select 'textarea.text[placeholder=Put in some text]'
235
+ end
236
+
80
237
  test 'input should generate a password field for password attributes' do
81
238
  with_input_for @user, :password, :password
82
239
  assert_select 'input[type=password].password#user_password'
83
240
  end
84
241
 
242
+ test 'input should generate a password field for password attributes that accept placeholder' do
243
+ with_input_for @user, :password, :password, :placeholder => 'Password Confirmation'
244
+ assert_select 'input[type=password].password[placeholder=Password Confirmation]#user_password'
245
+ end
246
+
85
247
  test 'input should generate a file field' do
86
248
  with_input_for @user, :name, :file
87
249
  assert_select 'input#user_name[type=file]'
88
250
  end
89
251
 
252
+ test "input should generate a file field that don't accept placeholder" do
253
+ with_input_for @user, :name, :file, :placeholder => 'Put in some text'
254
+ assert_no_select 'input[placeholder]'
255
+ end
256
+
257
+ test 'mapping input should generate an error if type is not found' do
258
+ with_concat_form_for(@user) do |f|
259
+ assert_raise(RuntimeError, "Could not find method for nil") do
260
+ SimpleForm::Inputs::MappingInput.new(f, "unknown", nil, nil, {}).input
261
+ end
262
+ end
263
+ end
264
+
90
265
  # HiddenInput
91
266
  test 'input should generate a hidden field' do
92
267
  with_input_for @user, :name, :hidden
@@ -104,6 +279,14 @@ class InputTest < ActionView::TestCase
104
279
  assert_no_select 'label'
105
280
  end
106
281
 
282
+ test 'required/optional options should not be generated for hidden inputs' do
283
+ with_input_for @user, :name, :hidden
284
+ assert_no_select 'input.required'
285
+ assert_no_select 'input[required]'
286
+ assert_no_select 'input.optional'
287
+ assert_select 'input.hidden#user_name'
288
+ end
289
+
107
290
  # PriorityInput
108
291
  test 'input should generate a country select field' do
109
292
  with_input_for @user, :country, :country
@@ -267,6 +450,28 @@ class InputTest < ActionView::TestCase
267
450
  assert_select 'select option[selected=selected]', '18'
268
451
  end
269
452
 
453
+ test 'input should set the correct value when using a collection that includes floats' do
454
+ with_input_for @user, :age, :select, :collection => [2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
455
+ assert_select 'select option[value="2.0"]'
456
+ assert_select 'select option[value="2.5"]'
457
+ end
458
+
459
+ test 'input should set the correct values when using a collection that uses mixed values' do
460
+ with_input_for @user, :age, :select, :collection => ["Hello Kitty", 2, 4.5, :johnny, nil, true, false]
461
+ assert_select 'select option[value="Hello Kitty"]'
462
+ assert_select 'select option[value="2"]'
463
+ assert_select 'select option[value="4.5"]'
464
+ assert_select 'select option[value="johnny"]'
465
+ assert_select 'select option[value=""]'
466
+ assert_select 'select option[value="true"]'
467
+ assert_select 'select option[value="false"]'
468
+ end
469
+
470
+ test 'input should include a blank option even if :include_blank is set to false if the collection includes a nil value' do
471
+ with_input_for @user, :age, :select, :collection => [nil], :include_blank => false
472
+ assert_select 'select option[value=""]'
473
+ end
474
+
270
475
  test 'input should automatically set include blank' do
271
476
  with_input_for @user, :age, :select, :collection => 18..30
272
477
  assert_select 'select option[value=]', ''
@@ -316,6 +521,22 @@ class InputTest < ActionView::TestCase
316
521
  assert_select 'label.collection_radio', 'Carlos'
317
522
  end
318
523
 
524
+ test 'input should allow overriding only label method for collections' do
525
+ with_input_for @user, :name, :radio,
526
+ :collection => ['Jose' , 'Carlos'],
527
+ :label_method => :upcase
528
+ assert_select 'label.collection_radio', 'JOSE'
529
+ assert_select 'label.collection_radio', 'CARLOS'
530
+ end
531
+
532
+ test 'input should allow overriding only value method for collections' do
533
+ with_input_for @user, :name, :radio,
534
+ :collection => ['Jose' , 'Carlos'],
535
+ :value_method => :upcase
536
+ assert_select 'input[type=radio][value=JOSE]'
537
+ assert_select 'input[type=radio][value=CARLOS]'
538
+ end
539
+
319
540
  test 'input should allow overriding label and value method for collections' do
320
541
  with_input_for @user, :name, :radio,
321
542
  :collection => ['Jose' , 'Carlos'],
@@ -327,6 +548,24 @@ class InputTest < ActionView::TestCase
327
548
  assert_select 'label.collection_radio', 'CARLOS'
328
549
  end
329
550
 
551
+ test 'input should allow overriding label and value method using a lambda for collections' do
552
+ with_input_for @user, :name, :radio,
553
+ :collection => ['Jose' , 'Carlos'],
554
+ :label_method => lambda { |i| i.upcase },
555
+ :value_method => lambda { |i| i.downcase }
556
+ assert_select 'input[type=radio][value=jose]'
557
+ assert_select 'input[type=radio][value=carlos]'
558
+ assert_select 'label.collection_radio', 'JOSE'
559
+ assert_select 'label.collection_radio', 'CARLOS'
560
+ end
561
+
562
+ test 'input should allow symbols for collections' do
563
+ with_input_for @user, :name, :select, :collection => [:jose, :carlos]
564
+ assert_select 'select.select#user_name'
565
+ assert_select 'select option[value=jose]', 'jose'
566
+ assert_select 'select option[value=carlos]', 'carlos'
567
+ end
568
+
330
569
  # With no object
331
570
  test 'input should be generated properly when object is not present' do
332
571
  with_input_for :project, :name, :string