simple_form 1.3.1 → 1.4.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.

@@ -1,12 +1,19 @@
1
1
  module SimpleForm
2
2
  module Inputs
3
3
  class StringInput < Base
4
+ extend MapType
5
+
6
+ map_type :string, :email, :search, :tel, :url, :to => :text_field
7
+ map_type :password, :to => :password_field
8
+
4
9
  def input
5
10
  input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
6
- input_html_options[:maxlength] ||= limit if limit
7
- input_html_options[:type] ||= input_type unless string?
11
+ input_html_options[:maxlength] ||= limit if limit && SimpleForm.html5
12
+ if password? || SimpleForm.html5
13
+ input_html_options[:type] ||= input_type unless string?
14
+ end
8
15
 
9
- @builder.text_field(attribute_name, input_html_options)
16
+ @builder.send(input_method, attribute_name, input_html_options)
10
17
  end
11
18
 
12
19
  def input_html_classes
@@ -26,6 +33,10 @@ module SimpleForm
26
33
  def string?
27
34
  input_type == :string
28
35
  end
36
+
37
+ def password?
38
+ input_type == :password
39
+ end
29
40
  end
30
41
  end
31
42
  end
@@ -10,7 +10,7 @@ module SimpleForm
10
10
  def map_type(*types)
11
11
  map_to = types.extract_options![:to]
12
12
  raise ArgumentError, "You need to give :to as option to map_type" unless map_to
13
- types.each { |t| mappings[t] = map_to }
13
+ self.mappings = mappings.merge types.each_with_object({}) { |t, m| m[t] = map_to }
14
14
  end
15
15
  end
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleForm
2
- VERSION = "1.3.1".freeze
2
+ VERSION = "1.4.0".freeze
3
3
  end
@@ -1,9 +1,11 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class BuilderTest < ActionView::TestCase
4
-
5
- def with_concat_form_for(object, &block)
6
- concat form_for(object, &block)
4
+ def with_custom_form_for(object, *args, &block)
5
+ with_concat_custom_form_for(object) do |f|
6
+ assert f.instance_of?(CustomFormBuilder)
7
+ yield f
8
+ end
7
9
  end
8
10
 
9
11
  def with_collection_radio(object, attribute, collection, value_method, text_method, options={}, html_options={})
@@ -116,10 +118,17 @@ class BuilderTest < ActionView::TestCase
116
118
  assert_select 'form li input[type=radio][value=false]#user_active_false'
117
119
  end
118
120
 
119
- test 'collection radio does not wrap items by default' do
121
+ test 'collection radio wrap items in a span tag by default' do
120
122
  with_collection_radio @user, :active, [true, false], :to_s, :to_s
121
123
 
122
- assert_no_select 'form li'
124
+ assert_select 'form span input[type=radio][value=true]#user_active_true + label'
125
+ assert_select 'form span input[type=radio][value=false]#user_active_false + label'
126
+ end
127
+
128
+ test 'collection radio does not wrap input inside the label' do
129
+ with_collection_radio @user, :active, [true, false], :to_s, :to_s
130
+
131
+ assert_no_select 'form label input'
123
132
  end
124
133
 
125
134
  # COLLECTION CHECK BOX
@@ -259,10 +268,17 @@ class BuilderTest < ActionView::TestCase
259
268
  assert_select 'form li input[type=checkbox][value=false]#user_active_false'
260
269
  end
261
270
 
262
- test 'collection check box does not wrap items by default' do
271
+ test 'collection check box wrap items in a span tag by default' do
272
+ with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
273
+
274
+ assert_select 'form span input[type=checkbox][value=true]#user_active_true + label'
275
+ assert_select 'form span input[type=checkbox][value=false]#user_active_false + label'
276
+ end
277
+
278
+ test 'collection check box does not wrap input inside the label' do
263
279
  with_collection_check_boxes @user, :active, [true, false], :to_s, :to_s
264
280
 
265
- assert_no_select 'form li'
281
+ assert_no_select 'form label input'
266
282
  end
267
283
 
268
284
  # SIMPLE FIELDS
@@ -273,4 +289,20 @@ class BuilderTest < ActionView::TestCase
273
289
  end
274
290
  end
275
291
  end
292
+
293
+ test 'fields for yields an instance of CustomBuilder if main builder is a CustomBuilder' do
294
+ with_custom_form_for(:user) do |f|
295
+ f.simple_fields_for(:company) do |company|
296
+ assert company.instance_of?(CustomFormBuilder)
297
+ end
298
+ end
299
+ end
300
+
301
+ test 'fields for yields an instance of FormBuilder if it was set in options' do
302
+ with_custom_form_for(:user) do |f|
303
+ f.simple_fields_for(:company, :builder => SimpleForm::FormBuilder) do |company|
304
+ assert company.instance_of?(SimpleForm::FormBuilder)
305
+ end
306
+ end
307
+ end
276
308
  end
@@ -13,6 +13,18 @@ class FormHelperTest < ActionView::TestCase
13
13
  assert_select 'form.simple_form'
14
14
  end
15
15
 
16
+ test 'simple form should use default browser validations by default' do
17
+ concat(simple_form_for(:user) do |f| end)
18
+ assert_no_select 'form[novalidate]'
19
+ end
20
+
21
+ test 'simple form should not use default browser validations if specified in the configuration options' do
22
+ swap SimpleForm, :browser_validations => false do
23
+ concat(simple_form_for(:user) do |f| end)
24
+ assert_select 'form[novalidate="novalidate"]'
25
+ end
26
+ end
27
+
16
28
  test 'simple form should add object name as css class to form when object is not present' do
17
29
  concat(simple_form_for(:user) do |f| end)
18
30
  assert_select 'form.simple_form.user'
@@ -96,6 +96,43 @@ class LabelTest < ActionView::TestCase
96
96
  end
97
97
  end
98
98
 
99
+ test 'label should do correct i18n lookup for nested models with nested translation' do
100
+ @user.company = Company.new(1, 'Empresa')
101
+
102
+ store_translations(:en, :simple_form => { :labels => {
103
+ :user => { :name => 'Usuario', :company => { :name => 'Nome da empresa' } }
104
+ } } ) do
105
+ with_concat_form_for @user do |f|
106
+ concat f.input :name
107
+ concat(f.simple_fields_for(:company) do |company_form|
108
+ concat(company_form.input :name)
109
+ end)
110
+ end
111
+
112
+ assert_select 'label[for=user_name]', /Usuario/
113
+ assert_select 'label[for=user_company_attributes_name]', /Nome da empresa/
114
+ end
115
+ end
116
+
117
+ test 'label should do correct i18n lookup for nested models with no nested translation' do
118
+ @user.company = Company.new(1, 'Empresa')
119
+
120
+ store_translations(:en, :simple_form => { :labels => {
121
+ :user => { :name => 'Usuario' },
122
+ :company => { :name => 'Nome da empresa' }
123
+ } } ) do
124
+ with_concat_form_for @user do |f|
125
+ concat f.input :name
126
+ concat(f.simple_fields_for(:company) do |company_form|
127
+ concat(company_form.input :name)
128
+ end)
129
+ end
130
+
131
+ assert_select 'label[for=user_name]', /Usuario/
132
+ assert_select 'label[for=user_company_attributes_name]', /Nome da empresa/
133
+ end
134
+ end
135
+
99
136
  test 'label should have css class from type' do
100
137
  with_label_for @user, :name, :string
101
138
  assert_select 'label.string'
@@ -205,4 +242,11 @@ class LabelTest < ActionView::TestCase
205
242
  with_label_for :project, :description, :string, :required => false
206
243
  assert_no_select 'label.required[for=project_description]'
207
244
  end
245
+
246
+ test 'label should add chosen label class' do
247
+ swap SimpleForm, :label_class => :my_custom_class do
248
+ with_label_for @user, :name, :string
249
+ assert_select 'label.my_custom_class'
250
+ end
251
+ end
208
252
  end
@@ -0,0 +1,21 @@
1
+ class StringInput < SimpleForm::Inputs::StringInput
2
+ def input
3
+ "<section>#{super}</section>".html_safe
4
+ end
5
+ end
6
+
7
+ class NumericInput < SimpleForm::Inputs::NumericInput
8
+ def input
9
+ "<section>#{super}</section>".html_safe
10
+ end
11
+ end
12
+
13
+ class CustomizedInput < SimpleForm::Inputs::StringInput
14
+ def input
15
+ "<section>#{super}</section>".html_safe
16
+ end
17
+
18
+ def input_method
19
+ :text_field
20
+ end
21
+ end
@@ -27,6 +27,12 @@ class FormBuilderTest < ActionView::TestCase
27
27
  end
28
28
  end
29
29
 
30
+ def with_full_error_for(object, *args)
31
+ with_concat_form_for(object) do |f|
32
+ f.full_error(*args)
33
+ end
34
+ end
35
+
30
36
  def with_hint_for(object, *args)
31
37
  with_concat_form_for(object) do |f|
32
38
  f.hint(*args)
@@ -186,6 +192,14 @@ class FormBuilderTest < ActionView::TestCase
186
192
  assert_select 'form input#user_avatar.file'
187
193
  end
188
194
 
195
+ test 'builder should generate file for attributes that are real db columns but have file methods' do
196
+ @user.home_picture = mock("file")
197
+ @user.home_picture.expects(:respond_to?).with(:mounted_as).returns(true)
198
+
199
+ with_form_for @user, :home_picture
200
+ assert_select 'form input#user_home_picture.file'
201
+ end
202
+
189
203
  test 'build should generate select if a collection is given' do
190
204
  with_form_for @user, :age, :collection => 1..60
191
205
  assert_select 'form select#user_age.select'
@@ -206,6 +220,13 @@ class FormBuilderTest < ActionView::TestCase
206
220
  end
207
221
 
208
222
  # COMMON OPTIONS
223
+ test 'builder should add chosen form class' do
224
+ swap SimpleForm, :form_class => :my_custom_class do
225
+ with_form_for @user, :name
226
+ assert_select 'form.my_custom_class'
227
+ end
228
+ end
229
+
209
230
  test 'builder should allow passing options to input' do
210
231
  with_form_for @user, :name, :input_html => { :class => 'my_input', :id => 'my_input' }
211
232
  assert_select 'form input#my_input.my_input.string'
@@ -362,6 +383,43 @@ class FormBuilderTest < ActionView::TestCase
362
383
  assert_select 'form div.input.required.string.field_with_errors'
363
384
  end
364
385
 
386
+ # ONLY THE INPUT TAG
387
+ test "builder input_field should only render the input tag, nothing else" do
388
+ with_concat_form_for(@user) do |f|
389
+ f.input_field :name
390
+ end
391
+ assert_select 'form > input.required.string'
392
+ assert_no_select 'div.string'
393
+ assert_no_select 'label'
394
+ assert_no_select '.hint'
395
+ end
396
+
397
+ test 'builder input_field should allow overriding default input type' do
398
+ with_concat_form_for(@user) do |f|
399
+ f.input_field :name, :as => :text
400
+ end
401
+
402
+ assert_no_select 'input#user_name'
403
+ assert_select 'textarea#user_name.text'
404
+ end
405
+
406
+ test 'builder input_field should allow passing options to input tag' do
407
+ with_concat_form_for(@user) do |f|
408
+ f.input_field :name, :id => 'name_input', :class => 'name'
409
+ end
410
+
411
+ assert_select 'input.string.name#name_input'
412
+ end
413
+
414
+ test 'builder input_field should generate an input tag with a clean HTML' do
415
+ with_concat_form_for(@user) do |f|
416
+ f.input_field :name, :as => :integer, :class => 'name'
417
+ end
418
+
419
+ assert_no_select 'input.integer[input_html]'
420
+ assert_no_select 'input.integer[as]'
421
+ end
422
+
365
423
  # WITHOUT OBJECT
366
424
  test 'builder should generate properly when object is not present' do
367
425
  with_form_for :project, :name
@@ -403,6 +461,22 @@ class FormBuilderTest < ActionView::TestCase
403
461
  assert_select 'span.error#name_error', "can't be blank"
404
462
  end
405
463
 
464
+ # FULL ERRORS
465
+ test 'builder should generate an full error tag for the attribute' do
466
+ with_full_error_for @user, :name
467
+ assert_select 'span.error', "Super User Name! can't be blank"
468
+ end
469
+
470
+ test 'builder should generate an full error tag with a clean HTML' do
471
+ with_full_error_for @user, :name
472
+ assert_no_select 'span.error[error_html]'
473
+ end
474
+
475
+ test 'builder should allow passing options to full error tag' do
476
+ with_full_error_for @user, :name, :id => 'name_error', :error_prefix => "Your name"
477
+ assert_select 'span.error#name_error', "Your name can't be blank"
478
+ end
479
+
406
480
  # HINTS
407
481
  test 'builder should generate a hint tag for the attribute' do
408
482
  store_translations(:en, :simple_form => { :hints => { :user => { :name => "Add your name" }}}) do
@@ -511,6 +585,36 @@ class FormBuilderTest < ActionView::TestCase
511
585
  end
512
586
  end
513
587
 
588
+ test 'builder preloads collection association' do
589
+ value = @user.tags
590
+ value.expects(:to_a).returns(value)
591
+ with_association_for @user, :tags
592
+ assert_select 'form select.select#user_tag_ids'
593
+ assert_select 'form select option[value=1]', 'Tag 1'
594
+ assert_select 'form select option[value=2]', 'Tag 2'
595
+ assert_select 'form select option[value=3]', 'Tag 3'
596
+ end
597
+
598
+ test 'builder does not preload collection association if preload false' do
599
+ value = @user.company
600
+ value.expects(:to_a).never
601
+ with_association_for @user, :company, :preload => false
602
+ assert_select 'form select.select#user_company_id'
603
+ assert_select 'form select option[value=1]', 'Company 1'
604
+ assert_select 'form select option[value=2]', 'Company 2'
605
+ assert_select 'form select option[value=3]', 'Company 3'
606
+ end
607
+
608
+ test 'builder does not preload non collection association' do
609
+ value = @user.company
610
+ value.expects(:to_a).never
611
+ with_association_for @user, :company, :preload => false
612
+ assert_select 'form select.select#user_company_id'
613
+ assert_select 'form select option[value=1]', 'Company 1'
614
+ assert_select 'form select option[value=2]', 'Company 2'
615
+ assert_select 'form select option[value=3]', 'Company 3'
616
+ end
617
+
514
618
  # ASSOCIATIONS - BELONGS TO
515
619
  test 'builder creates a select for belongs_to associations' do
516
620
  with_association_for @user, :company
@@ -611,4 +715,81 @@ class FormBuilderTest < ActionView::TestCase
611
715
  with_custom_form_for @user, :email
612
716
  assert_select 'form input[type=email]#user_email.custom'
613
717
  end
718
+
719
+ test 'form with CustomMapTypeFormBuilder should use custom map type builder' do
720
+ with_concat_custom_mapping_form_for(:user) do |user|
721
+ assert user.instance_of?(CustomMapTypeFormBuilder)
722
+ end
723
+ end
724
+
725
+ test 'form with CustomMapTypeFormBuilder should use custom mapping' do
726
+ with_concat_custom_mapping_form_for(:user) do |user|
727
+ assert_equal SimpleForm::Inputs::StringInput, user.class.mappings[:custom_type]
728
+ end
729
+ end
730
+
731
+ test 'form without CustomMapTypeFormBuilder should not use custom mapping' do
732
+ with_concat_form_for(:user) do |user|
733
+ assert_nil user.class.mappings[:custom_type]
734
+ end
735
+ end
736
+
737
+ # DISCOVERY
738
+ # Setup new inputs and remove them after the test.
739
+ def discovery(value=false)
740
+ swap SimpleForm, :cache_discovery => value do
741
+ begin
742
+ load "discovery_inputs.rb"
743
+ yield
744
+ ensure
745
+ SimpleForm::FormBuilder.discovery_cache.clear
746
+ Object.send :remove_const, :StringInput
747
+ Object.send :remove_const, :NumericInput
748
+ Object.send :remove_const, :CustomizedInput
749
+ end
750
+ end
751
+ end
752
+
753
+ test 'builder should not discover new inputs if cached' do
754
+ with_form_for @user, :name
755
+ assert_select 'form input#user_name.string'
756
+
757
+ discovery(true) do
758
+ with_form_for @user, :name
759
+ assert_no_select 'form section input#user_name.string'
760
+ end
761
+ end
762
+
763
+ test 'builder should discover new inputs' do
764
+ discovery do
765
+ with_form_for @user, :name, :as => :customized
766
+ assert_select 'form section input#user_name.string'
767
+ end
768
+ end
769
+
770
+ test 'builder should not discover new inputs if discovery is off' do
771
+ with_form_for @user, :name
772
+ assert_select 'form input#user_name.string'
773
+
774
+ swap SimpleForm, :inputs_discovery => false do
775
+ discovery do
776
+ with_form_for @user, :name
777
+ assert_no_select 'form section input#user_name.string'
778
+ end
779
+ end
780
+ end
781
+
782
+ test 'builder should discover new inputs from mappings if not cached' do
783
+ discovery do
784
+ with_form_for @user, :name
785
+ assert_select 'form section input#user_name.string'
786
+ end
787
+ end
788
+
789
+ test 'builder should discover new inputs from internal fallbacks if not cached' do
790
+ discovery do
791
+ with_form_for @user, :age
792
+ assert_select 'form section input#user_age.numeric.integer'
793
+ end
794
+ end
614
795
  end