simple_form 0.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of simple_form might be problematic. Click here for more details.
- data/README.rdoc +339 -6
- data/generators/simple_form_install/USAGE +3 -0
- data/generators/simple_form_install/simple_form_install_generator.rb +19 -0
- data/generators/simple_form_install/templates/simple_form.rb +38 -0
- data/init.rb +1 -0
- data/lib/simple_form.rb +57 -1
- data/lib/simple_form/action_view_extensions/builder.rb +122 -0
- data/lib/simple_form/action_view_extensions/form_helper.rb +33 -0
- data/lib/simple_form/action_view_extensions/instance_tag.rb +37 -0
- data/lib/simple_form/components.rb +8 -0
- data/lib/simple_form/components/errors.rb +35 -0
- data/lib/simple_form/components/hints.rb +21 -0
- data/lib/simple_form/components/labels.rb +68 -0
- data/lib/simple_form/components/wrapper.rb +21 -0
- data/lib/simple_form/form_builder.rb +332 -0
- data/lib/simple_form/i18n_cache.rb +22 -0
- data/lib/simple_form/inputs.rb +12 -0
- data/lib/simple_form/inputs/base.rb +107 -0
- data/lib/simple_form/inputs/block_input.rb +13 -0
- data/lib/simple_form/inputs/collection_input.rb +58 -0
- data/lib/simple_form/inputs/date_time_input.rb +18 -0
- data/lib/simple_form/inputs/hidden_input.rb +11 -0
- data/lib/simple_form/inputs/mapping_input.rb +23 -0
- data/lib/simple_form/inputs/priority_input.rb +20 -0
- data/lib/simple_form/inputs/text_field_input.rb +16 -0
- data/lib/simple_form/locale/en.yml +14 -0
- data/lib/simple_form/map_type.rb +13 -0
- data/lib/simple_form/version.rb +3 -0
- data/test/action_view_extensions/builder_test.rb +172 -0
- data/test/action_view_extensions/form_helper_test.rb +50 -0
- data/test/components/error_test.rb +45 -0
- data/test/components/hint_test.rb +78 -0
- data/test/components/label_test.rb +170 -0
- data/test/form_builder_test.rb +550 -0
- data/test/inputs_test.rb +337 -0
- data/test/simple_form_test.rb +9 -0
- data/test/support/country_select/init.rb +1 -0
- data/test/support/country_select/install.rb +2 -0
- data/test/support/country_select/lib/country_select.rb +84 -0
- data/test/support/country_select/uninstall.rb +1 -0
- data/test/support/misc_helpers.rb +29 -0
- data/test/support/mock_controller.rb +11 -0
- data/test/support/mock_response.rb +14 -0
- data/test/support/models.rb +100 -0
- data/test/test_helper.rb +60 -0
- metadata +50 -10
- data/CHANGELOG +0 -27
- data/Rakefile +0 -17
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FormHelperTest < ActionView::TestCase
|
4
|
+
|
5
|
+
test 'simple form for yields an instance of FormBuilder' do
|
6
|
+
simple_form_for :user do |f|
|
7
|
+
assert f.instance_of?(SimpleForm::FormBuilder)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
test 'simple form should add default class to form' do
|
12
|
+
simple_form_for :user do |f| end
|
13
|
+
assert_select 'form.simple_form'
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'simple form should add object name as css class to form when object is not present' do
|
17
|
+
simple_form_for :user do |f| end
|
18
|
+
assert_select 'form.simple_form.user'
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'simple form should add object class name as css class to form' do
|
22
|
+
simple_form_for @user do |f| end
|
23
|
+
assert_select 'form.simple_form.user'
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'pass options to simple form' do
|
27
|
+
simple_form_for :user, :url => '/account', :html => { :id => 'my_form' } do |f| end
|
28
|
+
assert_select 'form#my_form'
|
29
|
+
assert_select 'form[action=/account]'
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'fields for yields an instance of FormBuilder' do
|
33
|
+
simple_fields_for :user do |f|
|
34
|
+
assert f.instance_of?(SimpleForm::FormBuilder)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
test 'remote form for yields an instance of FormBuilder' do
|
39
|
+
simple_remote_form_for :user do |f|
|
40
|
+
assert f.instance_of?(SimpleForm::FormBuilder)
|
41
|
+
end
|
42
|
+
assert_select "form[onsubmit]"
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'pass options to simple remote form' do
|
46
|
+
simple_remote_form_for :user, :url => '/account', :html => { :id => 'my_form' } do |f| end
|
47
|
+
assert_select 'form#my_form'
|
48
|
+
assert_select 'form[action=/account]'
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ErrorTest < ActionView::TestCase
|
4
|
+
|
5
|
+
def with_error_for(object, attribute_name, type, options={}, &block)
|
6
|
+
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
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'error should not generate content for attribute without errors' do
|
17
|
+
with_error_for @user, :active, :boolean
|
18
|
+
assert_no_select 'span.error'
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'error should not generate messages when object is not present' do
|
22
|
+
with_error_for :project, :name, :string
|
23
|
+
assert_no_select 'span.error'
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'error should generate messages for attribute with single error' do
|
27
|
+
with_error_for @user, :name, :string
|
28
|
+
assert_select 'span.error', "can't be blank"
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'error should generate messages for attribute with several errors' do
|
32
|
+
with_error_for @user, :age, :numeric
|
33
|
+
assert_select 'span.error', 'is not a number and must be greater than 18'
|
34
|
+
end
|
35
|
+
|
36
|
+
test 'error should be able to pass html options' do
|
37
|
+
with_error_for @user, :name, :string, :error_html => { :id => 'error', :class => 'yay' }
|
38
|
+
assert_select 'span#error.error.yay'
|
39
|
+
end
|
40
|
+
|
41
|
+
test 'error should find errors on attribute and association' do
|
42
|
+
with_error_for @user, :company_id, :select, :setup_association => true
|
43
|
+
assert_select 'span.error', 'must be valid and company must be present'
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class HintTest < ActionView::TestCase
|
4
|
+
|
5
|
+
def with_hint_for(object, attribute_name, type, options={}, &block)
|
6
|
+
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
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'hint should not be generated by default' do
|
17
|
+
with_hint_for @user, :name, :string
|
18
|
+
assert_no_select 'span.hint'
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'hint should be generated with input text' do
|
22
|
+
with_hint_for @user, :name, :string, :hint => 'Use with care...'
|
23
|
+
assert_select 'span.hint', 'Use with care...'
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'hint uses the current component tag set' do
|
27
|
+
swap SimpleForm, :hint_tag => :p do
|
28
|
+
with_hint_for @user, :name, :string, :hint => 'Use with care...'
|
29
|
+
assert_select 'p.hint', 'Use with care...'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
test 'hint should use i18n based on model, action, and attribute to lookup translation' do
|
34
|
+
store_translations(:en, :simple_form => { :hints => { :user => {
|
35
|
+
:edit => { :name => 'Content of this input will be truncated...' }
|
36
|
+
} } }) do
|
37
|
+
with_hint_for @user, :name, :string
|
38
|
+
assert_select 'span.hint', 'Content of this input will be truncated...'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'hint should use i18n with model and attribute to lookup translation' do
|
43
|
+
store_translations(:en, :simple_form => { :hints => { :user => {
|
44
|
+
:name => 'Content of this input will be capitalized...'
|
45
|
+
} } }) do
|
46
|
+
with_hint_for @user, :name, :string
|
47
|
+
assert_select 'span.hint', 'Content of this input will be capitalized...'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'hint should use i18n just with attribute to lookup translation' do
|
52
|
+
store_translations(:en, :simple_form => { :hints => {
|
53
|
+
:name => 'Content of this input will be downcased...'
|
54
|
+
} }) do
|
55
|
+
with_hint_for @user, :name, :string
|
56
|
+
assert_select 'span.hint', 'Content of this input will be downcased...'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'hint should use i18n with lookup for association name' do
|
61
|
+
store_translations(:en, :simple_form => { :hints => {
|
62
|
+
:user => { :company => 'My company!' }
|
63
|
+
} } ) do
|
64
|
+
with_hint_for @user, :company_id, :string, :setup_association => true
|
65
|
+
assert_select 'span.hint', /My company!/
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
test 'hint should generate properly when object is not present' do
|
70
|
+
with_hint_for :project, :name, :string, :hint => 'Test without object'
|
71
|
+
assert_select 'span.hint', 'Test without object'
|
72
|
+
end
|
73
|
+
|
74
|
+
test 'hint should be able to pass html options' do
|
75
|
+
with_hint_for @user, :name, :string, :hint => 'Yay!', :hint_html => { :id => 'hint', :class => 'yay' }
|
76
|
+
assert_select 'span#hint.hint.yay'
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class LabelTest < ActionView::TestCase
|
4
|
+
|
5
|
+
setup do
|
6
|
+
SimpleForm::Inputs::Base.reset_i18n_cache :translate_required_html
|
7
|
+
end
|
8
|
+
|
9
|
+
def with_label_for(object, attribute_name, type, options={})
|
10
|
+
simple_form_for object do |f|
|
11
|
+
f.attribute_name = attribute_name
|
12
|
+
f.reflection = Association.new(Company, :company, {}) if options.delete(:setup_association)
|
13
|
+
f.input_type = type
|
14
|
+
f.options = options
|
15
|
+
|
16
|
+
concat(SimpleForm::Inputs::Base.new(f).label)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'label should generate a default humanized description' do
|
21
|
+
with_label_for @user, :name, :string
|
22
|
+
assert_select 'label[for=user_name]', /Name/
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'label should allow a customized description' do
|
26
|
+
with_label_for @user, :name, :string, :label => 'My label!'
|
27
|
+
assert_select 'label[for=user_name]', /My label!/
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'label should use human attribute name from object when available' do
|
31
|
+
with_label_for @user, :description, :text
|
32
|
+
assert_select 'label[for=user_description]', /User Description!/
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'label should use human attribute name based on association name' do
|
36
|
+
with_label_for @user, :company_id, :string, :setup_association => true
|
37
|
+
assert_select 'label', /Company Human Name!/
|
38
|
+
end
|
39
|
+
|
40
|
+
test 'label should use i18n based on model, action, and attribute to lookup translation' do
|
41
|
+
@controller.action_name = "new"
|
42
|
+
store_translations(:en, :simple_form => { :labels => { :user => {
|
43
|
+
:new => { :description => 'Nova descrição' }
|
44
|
+
} } } ) do
|
45
|
+
with_label_for @user, :description, :text
|
46
|
+
assert_select 'label[for=user_description]', /Nova descrição/
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
test 'label should fallback to new when action is create' do
|
51
|
+
@controller.action_name = "create"
|
52
|
+
store_translations(:en, :simple_form => { :labels => { :user => {
|
53
|
+
:new => { :description => 'Nova descrição' }
|
54
|
+
} } } ) do
|
55
|
+
with_label_for @user, :description, :text
|
56
|
+
assert_select 'label[for=user_description]', /Nova descrição/
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'label should use i18n based on model and attribute to lookup translation' do
|
61
|
+
store_translations(:en, :simple_form => { :labels => { :user => {
|
62
|
+
:description => 'Descrição'
|
63
|
+
} } } ) do
|
64
|
+
with_label_for @user, :description, :text
|
65
|
+
assert_select 'label[for=user_description]', /Descrição/
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
test 'input should use i18n based only on attribute to lookup translation' do
|
70
|
+
store_translations(:en, :simple_form => { :labels => { :age => 'Idade' } } ) do
|
71
|
+
with_label_for @user, :age, :integer
|
72
|
+
assert_select 'label[for=user_age]', /Idade/
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
test 'label should use i18n with lookup for association name' do
|
77
|
+
store_translations(:en, :simple_form => { :labels => {
|
78
|
+
:user => { :company => 'My company!' }
|
79
|
+
} } ) do
|
80
|
+
with_label_for @user, :company_id, :string, :setup_association => true
|
81
|
+
assert_select 'label[for=user_company_id]', /My company!/
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
test 'label should have css class from type' do
|
86
|
+
with_label_for @user, :name, :string
|
87
|
+
assert_select 'label.string'
|
88
|
+
with_label_for @user, :description, :text
|
89
|
+
assert_select 'label.text'
|
90
|
+
with_label_for @user, :age, :integer
|
91
|
+
assert_select 'label.integer'
|
92
|
+
with_label_for @user, :born_at, :date
|
93
|
+
assert_select 'label.date'
|
94
|
+
with_label_for @user, :created_at, :datetime
|
95
|
+
assert_select 'label.datetime'
|
96
|
+
end
|
97
|
+
|
98
|
+
test 'label should be required by default' do
|
99
|
+
with_label_for @user, :name, :string
|
100
|
+
assert_select 'label.required'
|
101
|
+
end
|
102
|
+
|
103
|
+
test 'label should be able to disable required' do
|
104
|
+
with_label_for @user, :name, :string, :required => false
|
105
|
+
assert_no_select 'label.required'
|
106
|
+
end
|
107
|
+
|
108
|
+
test 'label should add required text when required' do
|
109
|
+
with_label_for @user, :name, :string
|
110
|
+
assert_select 'label.required abbr[title=required]', '*'
|
111
|
+
end
|
112
|
+
|
113
|
+
test 'label should not have required text in no required inputs' do
|
114
|
+
with_label_for @user, :name, :string, :required => false
|
115
|
+
assert_no_select 'form label abbr'
|
116
|
+
end
|
117
|
+
|
118
|
+
test 'label should use i18n to find required text' do
|
119
|
+
store_translations(:en, :simple_form => { :required => { :text => 'campo requerido' }}) do
|
120
|
+
with_label_for @user, :name, :string
|
121
|
+
assert_select 'form label abbr[title=campo requerido]', '*'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
test 'label should use i18n to find required mark' do
|
126
|
+
store_translations(:en, :simple_form => { :required => { :mark => '*-*' }}) do
|
127
|
+
with_label_for @user, :name, :string
|
128
|
+
assert_select 'form label abbr', '*-*'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
test 'label should use i18n to find required string tag' do
|
133
|
+
store_translations(:en, :simple_form => { :required => { :html => '<span class="required" title="requerido">*</span>' }}) do
|
134
|
+
with_label_for @user, :name, :string
|
135
|
+
assert_no_select 'form label abbr'
|
136
|
+
assert_select 'form label span.required[title=requerido]', '*'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
test 'label should allow overwriting input id' do
|
141
|
+
with_label_for @user, :name, :string, :input_html => { :id => 'my_new_id' }
|
142
|
+
assert_select 'label[for=my_new_id]'
|
143
|
+
end
|
144
|
+
|
145
|
+
test 'label should use default input id when it was not overridden' do
|
146
|
+
with_label_for @user, :name, :string, :input_html => { :class => 'my_new_id' }
|
147
|
+
assert_select 'label[for=user_name]'
|
148
|
+
end
|
149
|
+
|
150
|
+
test 'label should be generated properly when object is not present' do
|
151
|
+
with_label_for :project, :name, :string
|
152
|
+
assert_select 'label[for=project_name]', /Name/
|
153
|
+
end
|
154
|
+
|
155
|
+
test 'label should use i18n properly when object is not present' do
|
156
|
+
store_translations(:en, :simple_form => { :labels => {
|
157
|
+
:project => { :name => 'Nome' }
|
158
|
+
} } ) do
|
159
|
+
with_label_for :project, :name, :string
|
160
|
+
assert_select 'label[for=project_name]', /Nome/
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
test 'label should add required by default when object is not present' do
|
165
|
+
with_label_for :project, :name, :string
|
166
|
+
assert_select 'label.required[for=project_name]'
|
167
|
+
with_label_for :project, :description, :string, :required => false
|
168
|
+
assert_no_select 'label.required[for=project_description]'
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,550 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FormBuilderTest < ActionView::TestCase
|
4
|
+
|
5
|
+
def with_form_for(object, *args, &block)
|
6
|
+
simple_form_for object do |f|
|
7
|
+
concat f.input(*args, &block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def with_button_for(object, *args)
|
12
|
+
simple_form_for object do |f|
|
13
|
+
concat f.button(*args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_error_for(object, *args)
|
18
|
+
simple_form_for object do |f|
|
19
|
+
concat f.error(*args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_hint_for(object, *args)
|
24
|
+
simple_form_for object do |f|
|
25
|
+
concat f.hint(*args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_label_for(object, *args)
|
30
|
+
simple_form_for object do |f|
|
31
|
+
concat f.label(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def with_association_for(object, *args)
|
36
|
+
simple_form_for object do |f|
|
37
|
+
concat f.association(*args)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# All
|
42
|
+
test 'nested simple fields should yields an instance of FormBuilder' do
|
43
|
+
simple_form_for :user do |f|
|
44
|
+
f.simple_fields_for :posts do |posts_form|
|
45
|
+
assert posts_form.instance_of?(SimpleForm::FormBuilder)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
test 'builder input is html safe' do
|
51
|
+
simple_form_for @user do |f|
|
52
|
+
assert f.input(:name).html_safe?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
test 'builder input should allow a block to configure input' do
|
57
|
+
with_form_for @user, :name do
|
58
|
+
concat text_field_tag :foo, :bar, :id => :cool
|
59
|
+
end
|
60
|
+
assert_no_select 'input.string'
|
61
|
+
assert_select 'input#cool'
|
62
|
+
end
|
63
|
+
|
64
|
+
# INPUT TYPES
|
65
|
+
test 'builder should generate text fields for string columns' do
|
66
|
+
with_form_for @user, :name
|
67
|
+
assert_select 'form input#user_name.string'
|
68
|
+
end
|
69
|
+
|
70
|
+
test 'builder should generate text areas for text columns' do
|
71
|
+
with_form_for @user, :description
|
72
|
+
assert_select 'form textarea#user_description.text'
|
73
|
+
end
|
74
|
+
|
75
|
+
test 'builder should generate a checkbox for boolean columns' do
|
76
|
+
with_form_for @user, :active
|
77
|
+
assert_select 'form input[type=checkbox]#user_active.boolean'
|
78
|
+
end
|
79
|
+
|
80
|
+
test 'builder should use integer text field for integer columns' do
|
81
|
+
with_form_for @user, :age
|
82
|
+
assert_select 'form input#user_age.integer'
|
83
|
+
end
|
84
|
+
|
85
|
+
test 'builder should generate decimal text field for decimal columns' do
|
86
|
+
with_form_for @user, :credit_limit
|
87
|
+
assert_select 'form input#user_credit_limit.decimal'
|
88
|
+
end
|
89
|
+
|
90
|
+
test 'builder should generate password fields for columns that matches password' do
|
91
|
+
with_form_for @user, :password
|
92
|
+
assert_select 'form input#user_password.password'
|
93
|
+
end
|
94
|
+
|
95
|
+
test 'builder should generate country fields for columns that matches country' do
|
96
|
+
with_form_for @user, :residence_country
|
97
|
+
assert_select 'form select#user_residence_country.country'
|
98
|
+
end
|
99
|
+
|
100
|
+
test 'builder should generate time_zone fields for columns that matches time_zone' do
|
101
|
+
with_form_for @user, :time_zone
|
102
|
+
assert_select 'form select#user_time_zone.time_zone'
|
103
|
+
end
|
104
|
+
|
105
|
+
test 'builder should generate date select for date columns' do
|
106
|
+
with_form_for @user, :born_at
|
107
|
+
assert_select 'form select#user_born_at_1i.date'
|
108
|
+
end
|
109
|
+
|
110
|
+
test 'builder should generate time select for time columns' do
|
111
|
+
with_form_for @user, :delivery_time
|
112
|
+
assert_select 'form select#user_delivery_time_4i.time'
|
113
|
+
end
|
114
|
+
|
115
|
+
test 'builder should generate datetime select for datetime columns' do
|
116
|
+
with_form_for @user, :created_at
|
117
|
+
assert_select 'form select#user_created_at_1i.datetime'
|
118
|
+
end
|
119
|
+
|
120
|
+
test 'builder should generate datetime select for timestamp columns' do
|
121
|
+
with_form_for @user, :updated_at
|
122
|
+
assert_select 'form select#user_updated_at_1i.datetime'
|
123
|
+
end
|
124
|
+
|
125
|
+
test 'builder should generate file for file columns' do
|
126
|
+
@user.avatar = mock("file")
|
127
|
+
@user.avatar.expects(:respond_to?).with(:mounted_as).returns(false)
|
128
|
+
@user.avatar.expects(:respond_to?).with(:file?).returns(false)
|
129
|
+
@user.avatar.expects(:respond_to?).with(:public_filename).returns(true)
|
130
|
+
|
131
|
+
with_form_for @user, :avatar
|
132
|
+
assert_select 'form input#user_avatar.file'
|
133
|
+
end
|
134
|
+
|
135
|
+
test 'build should generate select if a collection is given' do
|
136
|
+
with_form_for @user, :age, :collection => 1..60
|
137
|
+
assert_select 'form select#user_age.select'
|
138
|
+
end
|
139
|
+
|
140
|
+
test 'builder should allow overriding default input type for text' do
|
141
|
+
with_form_for @user, :name, :as => :text
|
142
|
+
assert_no_select 'form input#user_name'
|
143
|
+
assert_select 'form textarea#user_name.text'
|
144
|
+
|
145
|
+
with_form_for @user, :active, :as => :radio
|
146
|
+
assert_no_select 'form input[type=checkbox]'
|
147
|
+
assert_select 'form input.radio[type=radio]', :count => 2
|
148
|
+
|
149
|
+
with_form_for @user, :born_at, :as => :string
|
150
|
+
assert_no_select 'form select'
|
151
|
+
assert_select 'form input#user_born_at.string'
|
152
|
+
end
|
153
|
+
|
154
|
+
# COMMON OPTIONS
|
155
|
+
test 'builder should allow passing options to input' do
|
156
|
+
with_form_for @user, :name, :input_html => { :class => 'my_input', :id => 'my_input' }
|
157
|
+
assert_select 'form input#my_input.my_input.string'
|
158
|
+
end
|
159
|
+
|
160
|
+
test 'builder should generate a input with label' do
|
161
|
+
with_form_for @user, :name
|
162
|
+
assert_select 'form label.string[for=user_name]', /Name/
|
163
|
+
end
|
164
|
+
|
165
|
+
test 'builder should be able to disable the label for a input' do
|
166
|
+
with_form_for @user, :name, :label => false
|
167
|
+
assert_no_select 'form label'
|
168
|
+
end
|
169
|
+
|
170
|
+
test 'builder should use custom label' do
|
171
|
+
with_form_for @user, :name, :label => 'Yay!'
|
172
|
+
assert_select 'form label', /Yay!/
|
173
|
+
end
|
174
|
+
|
175
|
+
test 'builder should pass options to label' do
|
176
|
+
with_form_for @user, :name, :label_html => { :id => "cool" }
|
177
|
+
assert_select 'form label#cool', /Name/
|
178
|
+
end
|
179
|
+
|
180
|
+
test 'builder should not generate hints for a input' do
|
181
|
+
with_form_for @user, :name
|
182
|
+
assert_no_select 'span.hint'
|
183
|
+
end
|
184
|
+
|
185
|
+
test 'builder should be able to add a hint for a input' do
|
186
|
+
with_form_for @user, :name, :hint => 'test'
|
187
|
+
assert_select 'span.hint', 'test'
|
188
|
+
end
|
189
|
+
|
190
|
+
test 'builder should be able to disable a hint even if it exists in i18n' do
|
191
|
+
store_translations(:en, :simple_form => { :hints => { :name => 'Hint test' } }) do
|
192
|
+
with_form_for @user, :name, :hint => false
|
193
|
+
assert_no_select 'span.hint'
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
test 'builder should pass options to hint' do
|
198
|
+
with_form_for @user, :name, :hint => 'test', :hint_html => { :id => "cool" }
|
199
|
+
assert_select 'span.hint#cool', 'test'
|
200
|
+
end
|
201
|
+
|
202
|
+
test 'builder should generate errors for attribute without errors' do
|
203
|
+
with_form_for @user, :credit_limit
|
204
|
+
assert_no_select 'span.errors'
|
205
|
+
end
|
206
|
+
|
207
|
+
test 'builder should generate errors for attribute with errors' do
|
208
|
+
with_form_for @user, :name
|
209
|
+
assert_select 'span.error', "can't be blank"
|
210
|
+
end
|
211
|
+
|
212
|
+
test 'builder should be able to disable showing errors for a input' do
|
213
|
+
with_form_for @user, :name, :error => false
|
214
|
+
assert_no_select 'span.error'
|
215
|
+
end
|
216
|
+
|
217
|
+
test 'builder should pass options to errors' do
|
218
|
+
with_form_for @user, :name, :error_html => { :id => "cool" }
|
219
|
+
assert_select 'span.error#cool', "can't be blank"
|
220
|
+
end
|
221
|
+
|
222
|
+
test 'builder input should be required by default' do
|
223
|
+
with_form_for @user, :name
|
224
|
+
assert_select 'input.required#user_name'
|
225
|
+
end
|
226
|
+
|
227
|
+
test 'builder input should allow disabling required' do
|
228
|
+
with_form_for @user, :name, :required => false
|
229
|
+
assert_no_select 'input.required'
|
230
|
+
assert_select 'input.optional#user_name'
|
231
|
+
end
|
232
|
+
|
233
|
+
# WRAPPERS
|
234
|
+
test 'builder support wrapping around an specific tag' do
|
235
|
+
swap SimpleForm, :wrapper_tag => :p do
|
236
|
+
with_form_for @user, :name
|
237
|
+
assert_select 'form p label[for=user_name]'
|
238
|
+
assert_select 'form p input#user_name.string'
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
test 'builder wrapping tag adds default css classes' do
|
243
|
+
swap SimpleForm, :wrapper_tag => :p do
|
244
|
+
with_form_for @user, :name
|
245
|
+
assert_select 'form p.required.string'
|
246
|
+
|
247
|
+
with_form_for @user, :age, :required => false
|
248
|
+
assert_select 'form p.optional.integer'
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
test 'builder wrapping tag allow custom options to be given' do
|
253
|
+
swap SimpleForm, :wrapper_tag => :p do
|
254
|
+
with_form_for @user, :name, :wrapper_html => { :id => "super_cool", :class => 'yay' }
|
255
|
+
assert_select 'form p#super_cool.required.string.yay'
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
test 'builder allows wrapper tag to be given on demand' do
|
260
|
+
simple_form_for @user do |f|
|
261
|
+
concat f.input :name, :wrapper_tag => :b
|
262
|
+
end
|
263
|
+
assert_select 'form b.required.string'
|
264
|
+
end
|
265
|
+
|
266
|
+
# WITHOUT OBJECT
|
267
|
+
test 'builder should generate properly when object is not present' do
|
268
|
+
with_form_for :project, :name
|
269
|
+
assert_select 'form input.string#project_name'
|
270
|
+
end
|
271
|
+
|
272
|
+
test 'builder should generate password fields based on attribute name when object is not present' do
|
273
|
+
with_form_for :project, :password_confirmation
|
274
|
+
assert_select 'form input[type=password].password#project_password_confirmation'
|
275
|
+
end
|
276
|
+
|
277
|
+
test 'builder should generate text fields by default for all attributes when object is not present' do
|
278
|
+
with_form_for :project, :created_at
|
279
|
+
assert_select 'form input.string#project_created_at'
|
280
|
+
with_form_for :project, :budget
|
281
|
+
assert_select 'form input.string#project_budget'
|
282
|
+
end
|
283
|
+
|
284
|
+
test 'builder should allow overriding input type when object is not present' do
|
285
|
+
with_form_for :project, :created_at, :as => :datetime
|
286
|
+
assert_select 'form select.datetime#project_created_at_1i'
|
287
|
+
with_form_for :project, :budget, :as => :decimal
|
288
|
+
assert_select 'form input.decimal#project_budget'
|
289
|
+
end
|
290
|
+
|
291
|
+
# ERRORS
|
292
|
+
test 'builder should generate an error tag for the attribute' do
|
293
|
+
with_error_for @user, :name
|
294
|
+
assert_select 'span.error', "can't be blank"
|
295
|
+
end
|
296
|
+
|
297
|
+
test 'builder should allow passing options to error tag' do
|
298
|
+
with_error_for @user, :name, :id => 'name_error'
|
299
|
+
assert_select 'span.error#name_error', "can't be blank"
|
300
|
+
end
|
301
|
+
|
302
|
+
# HINTS
|
303
|
+
test 'builder should generate a hint tag for the attribute' do
|
304
|
+
store_translations(:en, :simple_form => { :hints => { :user => { :name => "Add your name" }}}) do
|
305
|
+
with_hint_for @user, :name
|
306
|
+
assert_select 'span.hint', 'Add your name'
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
test 'builder should generate a hint component tag for the given text' do
|
311
|
+
with_hint_for @user, 'Hello World!'
|
312
|
+
assert_select 'span.hint', 'Hello World!'
|
313
|
+
end
|
314
|
+
|
315
|
+
test 'builder should allow passing options to hint tag' do
|
316
|
+
with_hint_for @user, :name, :hint => 'Hello World!', :id => 'name_hint'
|
317
|
+
assert_select 'span.hint#name_hint', 'Hello World!'
|
318
|
+
end
|
319
|
+
|
320
|
+
# LABELS
|
321
|
+
test 'builder should generate a label for the attribute' do
|
322
|
+
with_label_for @user, :name
|
323
|
+
assert_select 'label.string[for=user_name]', /Name/
|
324
|
+
end
|
325
|
+
|
326
|
+
test 'builder should allow passing options to label tag' do
|
327
|
+
with_label_for @user, :name, :label => 'My label', :id => 'name_label'
|
328
|
+
assert_select 'label.string.required#name_label', /My label/
|
329
|
+
end
|
330
|
+
|
331
|
+
test 'builder should fallback to default label when string is given' do
|
332
|
+
with_label_for @user, :name, 'Nome do usuário'
|
333
|
+
assert_select 'label', 'Nome do usuário'
|
334
|
+
assert_no_select 'label.string'
|
335
|
+
end
|
336
|
+
|
337
|
+
test 'builder allows label order to be changed' do
|
338
|
+
swap SimpleForm, :label_text => lambda { |l, r| "#{l}:" } do
|
339
|
+
with_label_for @user, :age
|
340
|
+
assert_select 'label.integer[for=user_age]', "Age:"
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
# BUTTONS
|
345
|
+
test 'builder should create buttons' do
|
346
|
+
with_button_for :post, :submit
|
347
|
+
assert_select 'form input.submit[type=submit][value=Submit Post]'
|
348
|
+
end
|
349
|
+
|
350
|
+
test 'builder should create buttons for new records' do
|
351
|
+
@user.new_record!
|
352
|
+
with_button_for @user, :submit
|
353
|
+
assert_select 'form input.create[type=submit][value=Create User]'
|
354
|
+
end
|
355
|
+
|
356
|
+
test 'builder should create buttons for existing records' do
|
357
|
+
with_button_for @user, :submit
|
358
|
+
assert_select 'form input.update[type=submit][value=Update User]'
|
359
|
+
end
|
360
|
+
|
361
|
+
test 'builder should create buttons using human_name' do
|
362
|
+
@user.class.expects(:human_name).returns("Usuario")
|
363
|
+
with_button_for @user, :submit
|
364
|
+
assert_select 'form input[type=submit][value=Update Usuario]'
|
365
|
+
end
|
366
|
+
|
367
|
+
test 'builder should create object buttons with localized labels' do
|
368
|
+
store_translations(:en, :simple_form => { :buttons => {
|
369
|
+
:create => "Criar {{model}}", :update => "Atualizar {{model}}" }}) do
|
370
|
+
with_button_for @user, :submit
|
371
|
+
assert_select 'form input[type=submit][value=Atualizar User]'
|
372
|
+
|
373
|
+
@user.new_record!
|
374
|
+
with_button_for @user, :submit
|
375
|
+
assert_select 'form input[type=submit][value=Criar User]'
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
test 'builder should create non object buttons with localized labels' do
|
380
|
+
store_translations(:en, :simple_form => { :buttons => { :submit => "Enviar {{model}}" }}) do
|
381
|
+
with_button_for :post, :submit
|
382
|
+
assert_select 'form input[type=submit][value=Enviar Post]'
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
test 'builder forwards first options as button text' do
|
387
|
+
with_button_for :post, :submit, "Send it!"
|
388
|
+
assert_select 'form input[type=submit][value=Send it!]'
|
389
|
+
end
|
390
|
+
|
391
|
+
test 'builder forwards label option as button text' do
|
392
|
+
with_button_for :post, :submit, :label => "Send it!"
|
393
|
+
assert_select 'form input[type=submit][value=Send it!]'
|
394
|
+
end
|
395
|
+
|
396
|
+
test 'builder forwards all options except label to button' do
|
397
|
+
with_button_for :post, :submit, :class => "cool", :id => "super"
|
398
|
+
assert_select 'form input#super.submit.cool[type=submit]'
|
399
|
+
end
|
400
|
+
|
401
|
+
test 'builder calls any button tag' do
|
402
|
+
with_button_for :post, :image_submit, "/image/foo/bar"
|
403
|
+
assert_select 'form input[src=/image/foo/bar][type=image]'
|
404
|
+
end
|
405
|
+
|
406
|
+
# ASSOCIATIONS
|
407
|
+
test 'builder should not allow creating an association input when no object exists' do
|
408
|
+
assert_raise ArgumentError do
|
409
|
+
with_association_for :post, :author
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
test 'builder association with a block call simple_fields_for' do
|
414
|
+
simple_form_for @user do |f|
|
415
|
+
f.association :posts do |posts_form|
|
416
|
+
assert posts_form.instance_of?(SimpleForm::FormBuilder)
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
test 'builder association forwards collection to simple_fields_for' do
|
422
|
+
calls = 0
|
423
|
+
simple_form_for @user do |f|
|
424
|
+
f.association :company, :collection => Company.all do |c|
|
425
|
+
calls += 1
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
assert_equal calls, 3
|
430
|
+
end
|
431
|
+
|
432
|
+
# ASSOCIATIONS - BELONGS TO
|
433
|
+
test 'builder creates a select for belongs_to associations' do
|
434
|
+
with_association_for @user, :company
|
435
|
+
assert_select 'form select.select#user_company_id'
|
436
|
+
assert_select 'form select option[value=1]', 'Company 1'
|
437
|
+
assert_select 'form select option[value=2]', 'Company 2'
|
438
|
+
assert_select 'form select option[value=3]', 'Company 3'
|
439
|
+
end
|
440
|
+
|
441
|
+
test 'builder allows collection radio for belongs_to associations' do
|
442
|
+
with_association_for @user, :company, :as => :radio
|
443
|
+
assert_select 'form input.radio#user_company_id_1'
|
444
|
+
assert_select 'form input.radio#user_company_id_2'
|
445
|
+
assert_select 'form input.radio#user_company_id_3'
|
446
|
+
end
|
447
|
+
|
448
|
+
test 'builder marks the record which already belongs to the user' do
|
449
|
+
@user.company_id = 2
|
450
|
+
with_association_for @user, :company, :as => :radio
|
451
|
+
assert_no_select 'form input.radio#user_company_id_1[checked=checked]'
|
452
|
+
assert_select 'form input.radio#user_company_id_2[checked=checked]'
|
453
|
+
assert_no_select 'form input.radio#user_company_id_3[checked=checked]'
|
454
|
+
end
|
455
|
+
|
456
|
+
# ASSOCIATIONS - FINDERS
|
457
|
+
test 'builder should allow passing conditions to find collection' do
|
458
|
+
with_association_for @user, :company, :conditions => { :id => 1 }
|
459
|
+
assert_select 'form select.select#user_company_id'
|
460
|
+
assert_select 'form select option[value=1]'
|
461
|
+
assert_no_select 'form select option[value=2]'
|
462
|
+
assert_no_select 'form select option[value=3]'
|
463
|
+
end
|
464
|
+
|
465
|
+
test 'builder should use reflection conditions to find collection' do
|
466
|
+
with_association_for @user, :special_company
|
467
|
+
assert_select 'form select.select#user_special_company_id'
|
468
|
+
assert_select 'form select option[value=1]'
|
469
|
+
assert_no_select 'form select option[value=2]'
|
470
|
+
assert_no_select 'form select option[value=3]'
|
471
|
+
end
|
472
|
+
|
473
|
+
test 'builder should allow passing order to find collection' do
|
474
|
+
with_association_for @user, :company, :order => 'name'
|
475
|
+
assert_select 'form select.select#user_company_id'
|
476
|
+
assert_no_select 'form select option[value=1]'
|
477
|
+
assert_no_select 'form select option[value=2]'
|
478
|
+
assert_select 'form select option[value=3]'
|
479
|
+
end
|
480
|
+
|
481
|
+
test 'builder should allow passing include option to find collection' do
|
482
|
+
with_association_for @user, :company, :include => :city
|
483
|
+
assert_select 'form select.select#user_company_id'
|
484
|
+
assert_select 'form select option[value=1]'
|
485
|
+
assert_select 'form select option[value=2]'
|
486
|
+
assert_no_select 'form select option[value=3]'
|
487
|
+
end
|
488
|
+
|
489
|
+
test 'builder should allow passing joins option to find collection' do
|
490
|
+
with_association_for @user, :company, :joins => :city
|
491
|
+
assert_select 'form select.select#user_company_id'
|
492
|
+
assert_select 'form select option[value=2]'
|
493
|
+
assert_select 'form select option[value=3]'
|
494
|
+
assert_no_select 'form select option[value=1]'
|
495
|
+
end
|
496
|
+
|
497
|
+
test 'builder should allow overriding collection to association input' do
|
498
|
+
with_association_for @user, :company, :include_blank => false,
|
499
|
+
:collection => [Company.new(999, 'Teste')]
|
500
|
+
assert_select 'form select.select#user_company_id'
|
501
|
+
assert_no_select 'form select option[value=1]'
|
502
|
+
assert_select 'form select option[value=999]', 'Teste'
|
503
|
+
assert_select 'form select option', :count => 1
|
504
|
+
end
|
505
|
+
|
506
|
+
# ASSOCIATIONS - has_*
|
507
|
+
test 'builder does not allow has_one associations' do
|
508
|
+
assert_raise RuntimeError do
|
509
|
+
with_association_for @user, :first_company, :as => :radio
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
test 'builder creates a select with multiple options for collection associations' do
|
514
|
+
with_association_for @user, :tags
|
515
|
+
assert_select 'form select.select#user_tag_ids'
|
516
|
+
assert_select 'form select[multiple=multiple][size=5]'
|
517
|
+
assert_select 'form select option[value=1]', 'Tag 1'
|
518
|
+
assert_select 'form select option[value=2]', 'Tag 2'
|
519
|
+
assert_select 'form select option[value=3]', 'Tag 3'
|
520
|
+
end
|
521
|
+
|
522
|
+
test 'builder allows size to be overwritten for collection associations' do
|
523
|
+
with_association_for @user, :tags, :input_html => { :size => 10 }
|
524
|
+
assert_select 'form select[multiple=multiple][size=10]'
|
525
|
+
end
|
526
|
+
|
527
|
+
test 'builder marks all selected records which already belongs to user' do
|
528
|
+
@user.tag_ids = [1, 2]
|
529
|
+
with_association_for @user, :tags
|
530
|
+
assert_select 'form select option[value=1][selected=selected]'
|
531
|
+
assert_select 'form select option[value=2][selected=selected]'
|
532
|
+
assert_no_select 'form select option[value=3][selected=selected]'
|
533
|
+
end
|
534
|
+
|
535
|
+
test 'builder allows a collection of check boxes for collection associations' do
|
536
|
+
@user.tag_ids = [1, 2]
|
537
|
+
with_association_for @user, :tags, :as => :check_boxes
|
538
|
+
assert_select 'form input#user_tag_ids_1[type=checkbox]'
|
539
|
+
assert_select 'form input#user_tag_ids_2[type=checkbox]'
|
540
|
+
assert_select 'form input#user_tag_ids_3[type=checkbox]'
|
541
|
+
end
|
542
|
+
|
543
|
+
test 'builder marks all selected records for collection boxes' do
|
544
|
+
@user.tag_ids = [1, 2]
|
545
|
+
with_association_for @user, :tags, :as => :check_boxes
|
546
|
+
assert_select 'form input[type=checkbox][value=1][checked=checked]'
|
547
|
+
assert_select 'form input[type=checkbox][value=2][checked=checked]'
|
548
|
+
assert_no_select 'form input[type=checkbox][value=3][checked=checked]'
|
549
|
+
end
|
550
|
+
end
|