simple_form 1.5.2 → 2.0.0.rc
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.
- data/CHANGELOG.md +224 -0
- data/MIT-LICENSE +1 -1
- data/README.md +817 -0
- data/lib/generators/simple_form/install_generator.rb +15 -1
- data/lib/generators/simple_form/templates/README +12 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb.tt +173 -0
- data/lib/simple_form.rb +109 -43
- data/lib/simple_form/action_view_extensions/builder.rb +158 -53
- data/lib/simple_form/action_view_extensions/form_helper.rb +29 -22
- data/lib/simple_form/components.rb +11 -1
- data/lib/simple_form/components/errors.rb +6 -24
- data/lib/simple_form/components/hints.rb +7 -21
- data/lib/simple_form/components/html5.rb +26 -0
- data/lib/simple_form/components/labels.rb +15 -13
- data/lib/simple_form/components/maxlength.rb +41 -0
- data/lib/simple_form/components/min_max.rb +49 -0
- data/lib/simple_form/components/pattern.rb +34 -0
- data/lib/simple_form/components/placeholders.rb +5 -17
- data/lib/simple_form/components/readonly.rb +22 -0
- data/lib/simple_form/core_ext/hash.rb +16 -0
- data/lib/simple_form/error_notification.rb +8 -1
- data/lib/simple_form/form_builder.rb +86 -22
- data/lib/simple_form/helpers.rb +7 -4
- data/lib/simple_form/helpers/autofocus.rb +11 -0
- data/lib/simple_form/helpers/disabled.rb +15 -0
- data/lib/simple_form/helpers/readonly.rb +15 -0
- data/lib/simple_form/helpers/required.rb +7 -10
- data/lib/simple_form/helpers/validators.rb +4 -4
- data/lib/simple_form/inputs.rb +17 -13
- data/lib/simple_form/inputs/base.rb +50 -81
- data/lib/simple_form/inputs/boolean_input.rb +43 -4
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +21 -0
- data/lib/simple_form/inputs/collection_input.rb +27 -13
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +69 -0
- data/lib/simple_form/inputs/collection_select_input.rb +14 -0
- data/lib/simple_form/inputs/date_time_input.rb +2 -2
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +41 -0
- data/lib/simple_form/inputs/hidden_input.rb +3 -6
- data/lib/simple_form/inputs/numeric_input.rb +3 -51
- data/lib/simple_form/inputs/password_input.rb +1 -2
- data/lib/simple_form/inputs/priority_input.rb +2 -2
- data/lib/simple_form/inputs/range_input.rb +1 -3
- data/lib/simple_form/inputs/string_input.rb +6 -8
- data/lib/simple_form/inputs/text_input.rb +1 -2
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/wrappers.rb +8 -0
- data/lib/simple_form/wrappers/builder.rb +75 -0
- data/lib/simple_form/wrappers/many.rb +68 -0
- data/lib/simple_form/wrappers/root.rb +34 -0
- data/lib/simple_form/wrappers/single.rb +18 -0
- data/test/action_view_extensions/builder_test.rb +195 -100
- data/test/action_view_extensions/form_helper_test.rb +24 -2
- data/test/components/label_test.rb +20 -5
- data/test/form_builder/association_test.rb +167 -0
- data/test/form_builder/button_test.rb +28 -0
- data/test/{error_notification_test.rb → form_builder/error_notification_test.rb} +2 -1
- data/test/form_builder/error_test.rb +101 -0
- data/test/form_builder/general_test.rb +348 -0
- data/test/form_builder/hint_test.rb +115 -0
- data/test/form_builder/input_field_test.rb +51 -0
- data/test/form_builder/label_test.rb +51 -0
- data/test/form_builder/wrapper_test.rb +140 -0
- data/test/generators/simple_form_generator_test.rb +32 -0
- data/test/inputs/boolean_input_test.rb +91 -0
- data/test/inputs/collection_check_boxes_input_test.rb +224 -0
- data/test/inputs/collection_radio_buttons_input_test.rb +326 -0
- data/test/inputs/collection_select_input_test.rb +241 -0
- data/test/inputs/datetime_input_test.rb +85 -0
- data/test/inputs/disabled_test.rb +38 -0
- data/test/inputs/discovery_test.rb +61 -0
- data/test/inputs/file_input_test.rb +16 -0
- data/test/inputs/general_test.rb +69 -0
- data/test/inputs/grouped_collection_select_input_test.rb +109 -0
- data/test/inputs/hidden_input_test.rb +30 -0
- data/test/inputs/numeric_input_test.rb +167 -0
- data/test/inputs/priority_input_test.rb +43 -0
- data/test/inputs/readonly_test.rb +61 -0
- data/test/inputs/required_test.rb +113 -0
- data/test/inputs/string_input_test.rb +140 -0
- data/test/inputs/text_input_test.rb +24 -0
- data/test/{discovery_inputs.rb → support/discovery_inputs.rb} +0 -0
- data/test/support/misc_helpers.rb +48 -6
- data/test/support/mock_controller.rb +2 -2
- data/test/support/models.rb +20 -5
- data/test/test_helper.rb +5 -8
- metadata +123 -98
- data/.gitignore +0 -3
- data/.gitmodules +0 -3
- data/.travis.yml +0 -15
- data/CHANGELOG.rdoc +0 -159
- data/Gemfile +0 -9
- data/README.rdoc +0 -466
- data/Rakefile +0 -27
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +0 -93
- data/lib/simple_form/components/wrapper.rb +0 -38
- data/lib/simple_form/helpers/has_errors.rb +0 -15
- data/lib/simple_form/helpers/maxlength.rb +0 -24
- data/lib/simple_form/helpers/pattern.rb +0 -28
- data/simple_form.gemspec +0 -25
- data/test/components/error_test.rb +0 -56
- data/test/components/hint_test.rb +0 -74
- data/test/components/wrapper_test.rb +0 -63
- data/test/custom_components.rb +0 -7
- data/test/form_builder_test.rb +0 -930
- data/test/inputs_test.rb +0 -995
|
@@ -42,9 +42,31 @@ class FormHelperTest < ActionView::TestCase
|
|
|
42
42
|
assert_select 'form.simple_form.user'
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
test 'simple form should add
|
|
45
|
+
test 'simple form should add :as option as css class to form when object is not present' do
|
|
46
|
+
concat(simple_form_for(:user, :as => 'superuser') do |f| end)
|
|
47
|
+
assert_select 'form.simple_form.superuser'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
test 'simple form should add object class name with new prefix as css class to form if record is not persisted' do
|
|
51
|
+
@user.new_record!
|
|
46
52
|
concat(simple_form_for(@user) do |f| end)
|
|
47
|
-
assert_select 'form.simple_form.
|
|
53
|
+
assert_select 'form.simple_form.new_user'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
test 'simple form should add :as option with new prefix as css class to form if record is not persisted' do
|
|
57
|
+
@user.new_record!
|
|
58
|
+
concat(simple_form_for(@user, :as => 'superuser') do |f| end)
|
|
59
|
+
assert_select 'form.simple_form.new_superuser'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
test 'simple form should add edit class prefix as css class to form if record is persisted' do
|
|
63
|
+
concat(simple_form_for(@user) do |f| end)
|
|
64
|
+
assert_select 'form.simple_form.edit_user'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
test 'simple form should add :as options with edit prefix as css class to form if record is persisted' do
|
|
68
|
+
concat(simple_form_for(@user, :as => 'superuser') do |f| end)
|
|
69
|
+
assert_select 'form.simple_form.edit_superuser'
|
|
48
70
|
end
|
|
49
71
|
|
|
50
72
|
test 'simple form should not add object class to form if css_class is specified' do
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
require 'test_helper'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
# Isolated tests for label without triggering f.label.
|
|
5
|
+
class IsolatedLabelTest < ActionView::TestCase
|
|
5
6
|
setup do
|
|
6
7
|
SimpleForm::Inputs::Base.reset_i18n_cache :translate_required_html
|
|
7
8
|
end
|
|
@@ -71,16 +72,16 @@ class LabelTest < ActionView::TestCase
|
|
|
71
72
|
end
|
|
72
73
|
end
|
|
73
74
|
|
|
74
|
-
test 'input should use i18n
|
|
75
|
-
store_translations(:en, :simple_form => { :labels => { :age => 'Idade' } } ) do
|
|
75
|
+
test 'input should use i18n under defaults to lookup translation' do
|
|
76
|
+
store_translations(:en, :simple_form => { :labels => { :defaults => {:age => 'Idade'} } } ) do
|
|
76
77
|
with_label_for @user, :age, :integer
|
|
77
78
|
assert_select 'label[for=user_age]', /Idade/
|
|
78
79
|
end
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
test 'input should not use i18n label if translate is false' do
|
|
82
|
-
swap SimpleForm, :
|
|
83
|
-
store_translations(:en, :simple_form => { :labels => { :age => 'Idade' } } ) do
|
|
83
|
+
swap SimpleForm, :translate_labels => false do
|
|
84
|
+
store_translations(:en, :simple_form => { :labels => { :defaults => {:age => 'Idade'} } } ) do
|
|
84
85
|
with_label_for @user, :age, :integer
|
|
85
86
|
assert_select 'label[for=user_age]', /Age/
|
|
86
87
|
end
|
|
@@ -246,6 +247,11 @@ class LabelTest < ActionView::TestCase
|
|
|
246
247
|
assert_select 'label[for=project_name]', /Name/
|
|
247
248
|
end
|
|
248
249
|
|
|
250
|
+
test 'label should include for attribute for select collection' do
|
|
251
|
+
with_label_for @user, :sex, :select, :collection => [:male, :female]
|
|
252
|
+
assert_select 'label[for=user_sex]'
|
|
253
|
+
end
|
|
254
|
+
|
|
249
255
|
test 'label should use i18n properly when object is not present' do
|
|
250
256
|
store_translations(:en, :simple_form => { :labels => {
|
|
251
257
|
:project => { :name => 'Nome' }
|
|
@@ -268,4 +274,13 @@ class LabelTest < ActionView::TestCase
|
|
|
268
274
|
assert_select 'label.my_custom_class'
|
|
269
275
|
end
|
|
270
276
|
end
|
|
277
|
+
|
|
278
|
+
test 'label strips extra classes even when label_class is nil' do
|
|
279
|
+
swap SimpleForm, :label_class => nil do
|
|
280
|
+
with_label_for @user, :name, :string
|
|
281
|
+
assert_select "label[class='string required']"
|
|
282
|
+
assert_no_select "label[class='string required ']"
|
|
283
|
+
assert_no_select "label[class=' string required']"
|
|
284
|
+
end
|
|
285
|
+
end
|
|
271
286
|
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class AssociationTest < ActionView::TestCase
|
|
5
|
+
def with_association_for(object, *args)
|
|
6
|
+
with_concat_form_for(object) do |f|
|
|
7
|
+
f.association(*args)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test 'builder should not allow creating an association input when no object exists' do
|
|
12
|
+
assert_raise ArgumentError do
|
|
13
|
+
with_association_for :post, :author
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test 'builder association with a block calls simple_fields_for' do
|
|
18
|
+
simple_form_for @user do |f|
|
|
19
|
+
f.association :posts do |posts_form|
|
|
20
|
+
assert posts_form.instance_of?(SimpleForm::FormBuilder)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test 'builder association forwards collection to simple_fields_for' do
|
|
26
|
+
calls = 0
|
|
27
|
+
simple_form_for @user do |f|
|
|
28
|
+
f.association :company, :collection => Company.all do |c|
|
|
29
|
+
calls += 1
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
assert_equal 3, calls
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
test 'builder association marks input as required based on both association and attribute' do
|
|
37
|
+
swap SimpleForm, :required_by_default => false do
|
|
38
|
+
with_association_for @validating_user, :company, :collection => []
|
|
39
|
+
assert_select 'label.required'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test 'builder preloads collection association' do
|
|
44
|
+
value = @user.tags
|
|
45
|
+
value.expects(:to_a).returns(value)
|
|
46
|
+
with_association_for @user, :tags
|
|
47
|
+
assert_select 'form select.select#user_tag_ids'
|
|
48
|
+
assert_select 'form select option[value=1]', 'Tag 1'
|
|
49
|
+
assert_select 'form select option[value=2]', 'Tag 2'
|
|
50
|
+
assert_select 'form select option[value=3]', 'Tag 3'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
test 'builder does not preload collection association if preload is false' do
|
|
54
|
+
value = @user.company
|
|
55
|
+
value.expects(:to_a).never
|
|
56
|
+
with_association_for @user, :company, :preload => false
|
|
57
|
+
assert_select 'form select.select#user_company_id'
|
|
58
|
+
assert_select 'form select option[value=1]', 'Company 1'
|
|
59
|
+
assert_select 'form select option[value=2]', 'Company 2'
|
|
60
|
+
assert_select 'form select option[value=3]', 'Company 3'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
test 'builder does not preload non-collection association' do
|
|
64
|
+
value = @user.company
|
|
65
|
+
value.expects(:to_a).never
|
|
66
|
+
with_association_for @user, :company, :preload => false
|
|
67
|
+
assert_select 'form select.select#user_company_id'
|
|
68
|
+
assert_select 'form select option[value=1]', 'Company 1'
|
|
69
|
+
assert_select 'form select option[value=2]', 'Company 2'
|
|
70
|
+
assert_select 'form select option[value=3]', 'Company 3'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# ASSOCIATIONS - BELONGS TO
|
|
74
|
+
test 'builder creates a select for belongs_to associations' do
|
|
75
|
+
with_association_for @user, :company
|
|
76
|
+
assert_select 'form select.select#user_company_id'
|
|
77
|
+
assert_select 'form select option[value=1]', 'Company 1'
|
|
78
|
+
assert_select 'form select option[value=2]', 'Company 2'
|
|
79
|
+
assert_select 'form select option[value=3]', 'Company 3'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
test 'builder allows collection radio for belongs_to associations' do
|
|
83
|
+
with_association_for @user, :company, :as => :radio_buttons
|
|
84
|
+
assert_select 'form input.radio_buttons#user_company_id_1'
|
|
85
|
+
assert_select 'form input.radio_buttons#user_company_id_2'
|
|
86
|
+
assert_select 'form input.radio_buttons#user_company_id_3'
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
test 'builder marks the record which already belongs to the user' do
|
|
90
|
+
@user.company_id = 2
|
|
91
|
+
with_association_for @user, :company, :as => :radio_buttons
|
|
92
|
+
assert_no_select 'form input.radio_buttons#user_company_id_1[checked=checked]'
|
|
93
|
+
assert_select 'form input.radio_buttons#user_company_id_2[checked=checked]'
|
|
94
|
+
assert_no_select 'form input.radio_buttons#user_company_id_3[checked=checked]'
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# ASSOCIATIONS - FINDERS
|
|
98
|
+
test 'builder should use reflection conditions to find collection' do
|
|
99
|
+
with_association_for @user, :special_company
|
|
100
|
+
assert_select 'form select.select#user_special_company_id'
|
|
101
|
+
assert_select 'form select option[value=1]'
|
|
102
|
+
assert_no_select 'form select option[value=2]'
|
|
103
|
+
assert_no_select 'form select option[value=3]'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
test 'builder should allow overriding collection to association input' do
|
|
107
|
+
with_association_for @user, :company, :include_blank => false,
|
|
108
|
+
:collection => [Company.new(999, 'Teste')]
|
|
109
|
+
assert_select 'form select.select#user_company_id'
|
|
110
|
+
assert_no_select 'form select option[value=1]'
|
|
111
|
+
assert_select 'form select option[value=999]', 'Teste'
|
|
112
|
+
assert_select 'form select option', :count => 1
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# ASSOCIATIONS - has_*
|
|
116
|
+
test 'builder does not allow has_one associations' do
|
|
117
|
+
assert_raise RuntimeError do
|
|
118
|
+
with_association_for @user, :first_company, :as => :radio_buttons
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
test 'builder creates a select with multiple options for collection associations' do
|
|
123
|
+
with_association_for @user, :tags
|
|
124
|
+
assert_select 'form select.select#user_tag_ids'
|
|
125
|
+
assert_select 'form select[multiple=multiple][size=5]'
|
|
126
|
+
assert_select 'form select option[value=1]', 'Tag 1'
|
|
127
|
+
assert_select 'form select option[value=2]', 'Tag 2'
|
|
128
|
+
assert_select 'form select option[value=3]', 'Tag 3'
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
test 'builder allows size to be overwritten for collection associations' do
|
|
132
|
+
with_association_for @user, :tags, :input_html => { :size => 10 }
|
|
133
|
+
assert_select 'form select[multiple=multiple][size=10]'
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
test 'builder marks all selected records which already belongs to user' do
|
|
137
|
+
@user.tag_ids = [1, 2]
|
|
138
|
+
with_association_for @user, :tags
|
|
139
|
+
assert_select 'form select option[value=1][selected=selected]'
|
|
140
|
+
assert_select 'form select option[value=2][selected=selected]'
|
|
141
|
+
assert_no_select 'form select option[value=3][selected=selected]'
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
test 'builder allows a collection of check boxes for collection associations' do
|
|
145
|
+
@user.tag_ids = [1, 2]
|
|
146
|
+
with_association_for @user, :tags, :as => :check_boxes
|
|
147
|
+
assert_select 'form input#user_tag_ids_1[type=checkbox]'
|
|
148
|
+
assert_select 'form input#user_tag_ids_2[type=checkbox]'
|
|
149
|
+
assert_select 'form input#user_tag_ids_3[type=checkbox]'
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
test 'builder marks all selected records for collection boxes' do
|
|
153
|
+
@user.tag_ids = [1, 2]
|
|
154
|
+
with_association_for @user, :tags, :as => :check_boxes
|
|
155
|
+
assert_select 'form input[type=checkbox][value=1][checked=checked]'
|
|
156
|
+
assert_select 'form input[type=checkbox][value=2][checked=checked]'
|
|
157
|
+
assert_no_select 'form input[type=checkbox][value=3][checked=checked]'
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
test 'builder with collection support giving collection and item wrapper tags' do
|
|
161
|
+
with_association_for @user, :tags, :as => :check_boxes,
|
|
162
|
+
:collection_wrapper_tag => :ul, :item_wrapper_tag => :li
|
|
163
|
+
|
|
164
|
+
assert_select 'form ul', :count => 1
|
|
165
|
+
assert_select 'form ul li', :count => 3
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class ButtonTest < ActionView::TestCase
|
|
5
|
+
def with_button_for(object, *args)
|
|
6
|
+
with_concat_form_for(object) do |f|
|
|
7
|
+
f.button(*args)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test 'builder should create buttons' do
|
|
12
|
+
with_button_for :post, :submit
|
|
13
|
+
assert_select 'form input.button[type=submit][value=Save Post]'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
test 'builder should create buttons for records' do
|
|
17
|
+
@user.new_record!
|
|
18
|
+
with_button_for @user, :submit
|
|
19
|
+
assert_select 'form input.button[type=submit][value=Create User]'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test "builder should use the default class from the configuration" do
|
|
23
|
+
swap SimpleForm, :button_class => 'btn' do
|
|
24
|
+
with_button_for :post, :submit
|
|
25
|
+
assert_select 'form input.btn[type=submit][value=Save Post]'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
require 'test_helper'
|
|
3
3
|
|
|
4
|
+
# Tests for f.error_notification
|
|
4
5
|
class ErrorNotificationTest < ActionView::TestCase
|
|
5
|
-
|
|
6
6
|
def with_error_notification_for(object, options={}, &block)
|
|
7
7
|
with_concat_form_for(object) do |f|
|
|
8
8
|
f.error_notification(options)
|
|
@@ -11,6 +11,7 @@ class ErrorNotificationTest < ActionView::TestCase
|
|
|
11
11
|
|
|
12
12
|
test 'error notification is not generated when the object has no error' do
|
|
13
13
|
assert @validating_user.valid?
|
|
14
|
+
|
|
14
15
|
with_error_notification_for @validating_user
|
|
15
16
|
assert_no_select 'p.error_notification'
|
|
16
17
|
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
# Tests for f.error and f.full_error
|
|
4
|
+
class ErrorTest < ActionView::TestCase
|
|
5
|
+
def with_error_for(object, *args)
|
|
6
|
+
with_concat_form_for(object) do |f|
|
|
7
|
+
f.error(*args)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def with_full_error_for(object, *args)
|
|
12
|
+
with_concat_form_for(object) do |f|
|
|
13
|
+
f.full_error(*args)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test 'error should not generate content for attribute without errors' do
|
|
18
|
+
with_error_for @user, :active
|
|
19
|
+
assert_no_select 'span.error'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test 'error should not generate messages when object is not present' do
|
|
23
|
+
with_error_for :project, :name
|
|
24
|
+
assert_no_select 'span.error'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
test "error should not generate messages when object doesn't respond to errors method" do
|
|
28
|
+
@user.instance_eval { undef errors }
|
|
29
|
+
with_error_for @user, :name
|
|
30
|
+
assert_no_select 'span.error'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
test 'error should generate messages for attribute with single error' do
|
|
34
|
+
with_error_for @user, :name
|
|
35
|
+
assert_select 'span.error', "can't be blank"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test 'error should generate messages for attribute with one error when using first' do
|
|
39
|
+
swap SimpleForm, :error_method => :first do
|
|
40
|
+
with_error_for @user, :age
|
|
41
|
+
assert_select 'span.error', 'is not a number'
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
test 'error should generate messages for attribute with several errors when using to_sentence' do
|
|
46
|
+
swap SimpleForm, :error_method => :to_sentence do
|
|
47
|
+
with_error_for @user, :age
|
|
48
|
+
assert_select 'span.error', 'is not a number and must be greater than 18'
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test 'error should be able to pass html options' do
|
|
53
|
+
with_error_for @user, :name, :id => 'error', :class => 'yay'
|
|
54
|
+
assert_select 'span#error.error.yay'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
test 'error should find errors on attribute and association' do
|
|
58
|
+
with_error_for @user, :company_id, :as => :select,
|
|
59
|
+
:error_method => :to_sentence, :reflection => Association.new(Company, :company, {})
|
|
60
|
+
assert_select 'span.error', 'must be valid and company must be present'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
test 'error should generate an error tag with a clean HTML' do
|
|
64
|
+
with_error_for @user, :name
|
|
65
|
+
assert_no_select 'span.error[error_html]'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
test 'error should generate an error tag with a clean HTML when errors options are present' do
|
|
69
|
+
with_error_for @user, :name, :error_tag => :p, :error_prefix => 'Name', :error_method => :first
|
|
70
|
+
assert_no_select 'p.error[error_html]'
|
|
71
|
+
assert_no_select 'p.error[error_tag]'
|
|
72
|
+
assert_no_select 'p.error[error_prefix]'
|
|
73
|
+
assert_no_select 'p.error[error_method]'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# FULL ERRORS
|
|
77
|
+
|
|
78
|
+
test 'full error should generate an full error tag for the attribute' do
|
|
79
|
+
with_full_error_for @user, :name
|
|
80
|
+
assert_select 'span.error', "Super User Name! can't be blank"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
test 'full error should generate an full error tag with a clean HTML' do
|
|
84
|
+
with_full_error_for @user, :name
|
|
85
|
+
assert_no_select 'span.error[error_html]'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
test 'full error should allow passing options to full error tag' do
|
|
89
|
+
with_full_error_for @user, :name, :id => 'name_error', :error_prefix => "Your name"
|
|
90
|
+
assert_select 'span.error#name_error', "Your name can't be blank"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# CUSTOM WRAPPERS
|
|
94
|
+
|
|
95
|
+
test 'error with custom wrappers works' do
|
|
96
|
+
swap_wrapper do
|
|
97
|
+
with_error_for @user, :name
|
|
98
|
+
assert_select 'span.omg_error', "can't be blank"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
|
|
4
|
+
class FormBuilderTest < ActionView::TestCase
|
|
5
|
+
def with_custom_form_for(object, *args, &block)
|
|
6
|
+
with_concat_custom_form_for(object) do |f|
|
|
7
|
+
f.input(*args, &block)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test 'nested simple fields should yield an instance of FormBuilder' do
|
|
12
|
+
simple_form_for :user do |f|
|
|
13
|
+
f.simple_fields_for :posts do |posts_form|
|
|
14
|
+
assert posts_form.instance_of?(SimpleForm::FormBuilder)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test 'builder input is html safe' do
|
|
20
|
+
simple_form_for @user do |f|
|
|
21
|
+
assert f.input(:name).html_safe?
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test 'builder input should allow a block to configure input' do
|
|
26
|
+
with_form_for @user, :name do
|
|
27
|
+
text_field_tag :foo, :bar, :id => :cool
|
|
28
|
+
end
|
|
29
|
+
assert_no_select 'input.string'
|
|
30
|
+
assert_select 'input#cool'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
test 'builder should allow adding custom input mappings for default input types' do
|
|
34
|
+
swap SimpleForm, :input_mappings => { /count$/ => :integer } do
|
|
35
|
+
with_form_for @user, :post_count
|
|
36
|
+
assert_no_select 'form input#user_post_count.string'
|
|
37
|
+
assert_select 'form input#user_post_count.numeric.integer'
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test 'builder should allow adding custom input mappings for integer input types' do
|
|
42
|
+
swap SimpleForm, :input_mappings => { /lock_version/ => :hidden } do
|
|
43
|
+
with_form_for @user, :lock_version
|
|
44
|
+
assert_no_select 'form input#user_lock_version.integer'
|
|
45
|
+
assert_select 'form input#user_lock_version.hidden'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
test 'builder uses the first matching custom input map when more than one matches' do
|
|
50
|
+
swap SimpleForm, :input_mappings => { /count$/ => :integer, /^post_/ => :password } do
|
|
51
|
+
with_form_for @user, :post_count
|
|
52
|
+
assert_no_select 'form input#user_post_count.password'
|
|
53
|
+
assert_select 'form input#user_post_count.numeric.integer'
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
test 'builder uses the custom map only for matched attributes' do
|
|
58
|
+
swap SimpleForm, :input_mappings => { /lock_version/ => :hidden } do
|
|
59
|
+
with_form_for @user, :post_count
|
|
60
|
+
assert_no_select 'form input#user_post_count.hidden'
|
|
61
|
+
assert_select 'form input#user_post_count.string'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# INPUT TYPES
|
|
66
|
+
test 'builder should generate text fields for string columns' do
|
|
67
|
+
with_form_for @user, :name
|
|
68
|
+
assert_select 'form input#user_name.string'
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
test 'builder should generate text areas for text columns' do
|
|
72
|
+
with_form_for @user, :description
|
|
73
|
+
assert_select 'form textarea#user_description.text'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
test 'builder should generate a checkbox for boolean columns' do
|
|
77
|
+
with_form_for @user, :active
|
|
78
|
+
assert_select 'form input[type=checkbox]#user_active.boolean'
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
test 'builder should use integer text field for integer columns' do
|
|
82
|
+
with_form_for @user, :age
|
|
83
|
+
assert_select 'form input#user_age.numeric.integer'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
test 'builder should generate decimal text field for decimal columns' do
|
|
87
|
+
with_form_for @user, :credit_limit
|
|
88
|
+
assert_select 'form input#user_credit_limit.numeric.decimal'
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
test 'builder should generate password fields for columns that matches password' do
|
|
92
|
+
with_form_for @user, :password
|
|
93
|
+
assert_select 'form input#user_password.password'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
test 'builder should generate country fields for columns that matches country' do
|
|
97
|
+
with_form_for @user, :residence_country
|
|
98
|
+
assert_select 'form select#user_residence_country.country'
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
test 'builder should generate time_zone fields for columns that matches time_zone' do
|
|
102
|
+
with_form_for @user, :time_zone
|
|
103
|
+
assert_select 'form select#user_time_zone.time_zone'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
test 'builder should generate email fields for columns that matches email' do
|
|
107
|
+
with_form_for @user, :email
|
|
108
|
+
assert_select 'form input#user_email.string.email'
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
test 'builder should generate tel fields for columns that matches phone' do
|
|
112
|
+
with_form_for @user, :phone_number
|
|
113
|
+
assert_select 'form input#user_phone_number.string.tel'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
test 'builder should generate url fields for columns that matches url' do
|
|
117
|
+
with_form_for @user, :url
|
|
118
|
+
assert_select 'form input#user_url.string.url'
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
test 'builder should generate date select for date columns' do
|
|
122
|
+
with_form_for @user, :born_at
|
|
123
|
+
assert_select 'form select#user_born_at_1i.date'
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
test 'builder should generate time select for time columns' do
|
|
127
|
+
with_form_for @user, :delivery_time
|
|
128
|
+
assert_select 'form select#user_delivery_time_4i.time'
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
test 'builder should generate datetime select for datetime columns' do
|
|
132
|
+
with_form_for @user, :created_at
|
|
133
|
+
assert_select 'form select#user_created_at_1i.datetime'
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
test 'builder should generate datetime select for timestamp columns' do
|
|
137
|
+
with_form_for @user, :updated_at
|
|
138
|
+
assert_select 'form select#user_updated_at_1i.datetime'
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
test 'builder should generate file for file columns' do
|
|
142
|
+
@user.avatar = mock("file")
|
|
143
|
+
@user.avatar.expects(:respond_to?).with(:mounted_as).returns(false)
|
|
144
|
+
@user.avatar.expects(:respond_to?).with(:file?).returns(false)
|
|
145
|
+
@user.avatar.expects(:respond_to?).with(:public_filename).returns(true)
|
|
146
|
+
|
|
147
|
+
with_form_for @user, :avatar
|
|
148
|
+
assert_select 'form input#user_avatar.file'
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
test 'builder should generate file for attributes that are real db columns but have file methods' do
|
|
152
|
+
@user.home_picture = mock("file")
|
|
153
|
+
@user.home_picture.expects(:respond_to?).with(:mounted_as).returns(true)
|
|
154
|
+
|
|
155
|
+
with_form_for @user, :home_picture
|
|
156
|
+
assert_select 'form input#user_home_picture.file'
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
test 'build should generate select if a collection is given' do
|
|
160
|
+
with_form_for @user, :age, :collection => 1..60
|
|
161
|
+
assert_select 'form select#user_age.select'
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
test 'builder should allow overriding default input type for text' do
|
|
165
|
+
with_form_for @user, :name, :as => :text
|
|
166
|
+
assert_no_select 'form input#user_name'
|
|
167
|
+
assert_select 'form textarea#user_name.text'
|
|
168
|
+
|
|
169
|
+
with_form_for @user, :active, :as => :radio_buttons
|
|
170
|
+
assert_no_select 'form input[type=checkbox]'
|
|
171
|
+
assert_select 'form input.radio_buttons[type=radio]', :count => 2
|
|
172
|
+
|
|
173
|
+
with_form_for @user, :born_at, :as => :string
|
|
174
|
+
assert_no_select 'form select'
|
|
175
|
+
assert_select 'form input#user_born_at.string'
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# COMMON OPTIONS
|
|
179
|
+
test 'builder should add chosen form class' do
|
|
180
|
+
swap SimpleForm, :form_class => :my_custom_class do
|
|
181
|
+
with_form_for @user, :name
|
|
182
|
+
assert_select 'form.my_custom_class'
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
test 'builder should allow passing options to input' do
|
|
187
|
+
with_form_for @user, :name, :input_html => { :class => 'my_input', :id => 'my_input' }
|
|
188
|
+
assert_select 'form input#my_input.my_input.string'
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
test 'builder should not propagate input options to wrapper' do
|
|
192
|
+
with_form_for @user, :name, :input_html => { :class => 'my_input', :id => 'my_input' }
|
|
193
|
+
assert_no_select 'form div.input.my_input.string'
|
|
194
|
+
assert_select 'form input#my_input.my_input.string'
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
test 'builder should generate a input with label' do
|
|
198
|
+
with_form_for @user, :name
|
|
199
|
+
assert_select 'form label.string[for=user_name]', /Name/
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
test 'builder should be able to disable the label for a input' do
|
|
203
|
+
with_form_for @user, :name, :label => false
|
|
204
|
+
assert_no_select 'form label'
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
test 'builder should use custom label' do
|
|
208
|
+
with_form_for @user, :name, :label => 'Yay!'
|
|
209
|
+
assert_select 'form label', /Yay!/
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
test 'builder should pass options to label' do
|
|
213
|
+
with_form_for @user, :name, :label_html => { :id => "cool" }
|
|
214
|
+
assert_select 'form label#cool', /Name/
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
test 'builder should not generate hints for a input' do
|
|
218
|
+
with_form_for @user, :name
|
|
219
|
+
assert_no_select 'span.hint'
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
test 'builder should be able to add a hint for a input' do
|
|
223
|
+
with_form_for @user, :name, :hint => 'test'
|
|
224
|
+
assert_select 'span.hint', 'test'
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
test 'builder should be able to disable a hint even if it exists in i18n' do
|
|
228
|
+
store_translations(:en, :simple_form => { :hints => { :name => 'Hint test' } }) do
|
|
229
|
+
with_form_for @user, :name, :hint => false
|
|
230
|
+
assert_no_select 'span.hint'
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
test 'builder should pass options to hint' do
|
|
235
|
+
with_form_for @user, :name, :hint => 'test', :hint_html => { :id => "cool" }
|
|
236
|
+
assert_select 'span.hint#cool', 'test'
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
test 'builder should generate errors for attribute without errors' do
|
|
240
|
+
with_form_for @user, :credit_limit
|
|
241
|
+
assert_no_select 'span.errors'
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
test 'builder should generate errors for attribute with errors' do
|
|
245
|
+
with_form_for @user, :name
|
|
246
|
+
assert_select 'span.error', "can't be blank"
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
test 'builder should be able to disable showing errors for a input' do
|
|
250
|
+
with_form_for @user, :name, :error => false
|
|
251
|
+
assert_no_select 'span.error'
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
test 'builder should pass options to errors' do
|
|
255
|
+
with_form_for @user, :name, :error_html => { :id => "cool" }
|
|
256
|
+
assert_select 'span.error#cool', "can't be blank"
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
test 'placeholder should not be generated when set to false' do
|
|
260
|
+
store_translations(:en, :simple_form => { :placeholders => { :user => {
|
|
261
|
+
:name => 'Name goes here'
|
|
262
|
+
} } }) do
|
|
263
|
+
with_form_for @user, :name, :placeholder => false
|
|
264
|
+
assert_no_select 'input[placeholder]'
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# DEFAULT OPTIONS
|
|
269
|
+
test 'builder should receive a default argument and pass it to the inputs' do
|
|
270
|
+
with_concat_form_for @user, :defaults => { :input_html => { :class => 'default_class' } } do |f|
|
|
271
|
+
f.input :name
|
|
272
|
+
end
|
|
273
|
+
assert_select 'input.default_class'
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
test 'builder should receive a default argument and pass it to the inputs, respecting the specific options' do
|
|
277
|
+
with_concat_form_for @user, :defaults => { :input_html => { :class => 'default_class' } } do |f|
|
|
278
|
+
f.input :name, :input_html => { :id => 'specific_id' }
|
|
279
|
+
end
|
|
280
|
+
assert_select 'input.default_class#specific_id'
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
test 'builder should receive a default argument and pass it to the inputs, overwriting the defaults with specific options' do
|
|
284
|
+
with_concat_form_for @user, :defaults => { :input_html => { :class => 'default_class', :id => 'default_id' } } do |f|
|
|
285
|
+
f.input :name, :input_html => { :id => 'specific_id' }
|
|
286
|
+
end
|
|
287
|
+
assert_select 'input.default_class#specific_id'
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
test 'builder should receive a default argument and pass it to the inputs without changing the defaults' do
|
|
291
|
+
with_concat_form_for @user, :defaults => { :input_html => { :class => 'default_class', :id => 'default_id' } } do |f|
|
|
292
|
+
concat(f.input :name)
|
|
293
|
+
concat(f.input :credit_limit)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
assert_select "input.string.default_class[name='user[name]']"
|
|
297
|
+
assert_no_select "input.string[name='user[credit_limit]']"
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# WITHOUT OBJECT
|
|
301
|
+
test 'builder should generate properly when object is not present' do
|
|
302
|
+
with_form_for :project, :name
|
|
303
|
+
assert_select 'form input.string#project_name'
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
test 'builder should generate password fields based on attribute name when object is not present' do
|
|
307
|
+
with_form_for :project, :password_confirmation
|
|
308
|
+
assert_select 'form input[type=password].password#project_password_confirmation'
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
test 'builder should generate text fields by default for all attributes when object is not present' do
|
|
312
|
+
with_form_for :project, :created_at
|
|
313
|
+
assert_select 'form input.string#project_created_at'
|
|
314
|
+
with_form_for :project, :budget
|
|
315
|
+
assert_select 'form input.string#project_budget'
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
test 'builder should allow overriding input type when object is not present' do
|
|
319
|
+
with_form_for :project, :created_at, :as => :datetime
|
|
320
|
+
assert_select 'form select.datetime#project_created_at_1i'
|
|
321
|
+
with_form_for :project, :budget, :as => :decimal
|
|
322
|
+
assert_select 'form input.decimal#project_budget'
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# CUSTOM FORM BUILDER
|
|
326
|
+
test 'custom builder should inherit mappings' do
|
|
327
|
+
with_custom_form_for @user, :email
|
|
328
|
+
assert_select 'form input[type=email]#user_email.custom'
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
test 'form with CustomMapTypeFormBuilder should use custom map type builder' do
|
|
332
|
+
with_concat_custom_mapping_form_for(:user) do |user|
|
|
333
|
+
assert user.instance_of?(CustomMapTypeFormBuilder)
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
test 'form with CustomMapTypeFormBuilder should use custom mapping' do
|
|
338
|
+
with_concat_custom_mapping_form_for(:user) do |user|
|
|
339
|
+
assert_equal SimpleForm::Inputs::StringInput, user.class.mappings[:custom_type]
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
test 'form without CustomMapTypeFormBuilder should not use custom mapping' do
|
|
344
|
+
with_concat_form_for(:user) do |user|
|
|
345
|
+
assert_nil user.class.mappings[:custom_type]
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|