formtastic 2.1.0 → 4.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.
- checksums.yaml +7 -0
- data/.gitattributes +1 -0
- data/.github/workflows/test.yml +61 -0
- data/.gitignore +4 -2
- data/CHANGELOG.md +52 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +105 -0
- data/MIT-LICENSE +1 -1
- data/{README.textile → README.md} +204 -219
- data/RELEASE_PROCESS +3 -1
- data/Rakefile +27 -29
- data/app/assets/stylesheets/formtastic.css +3 -2
- data/bin/appraisal +8 -0
- data/formtastic.gemspec +11 -14
- data/gemfiles/rails_5.2/Gemfile +5 -0
- data/gemfiles/rails_6.0/Gemfile +5 -0
- data/gemfiles/rails_6.1/Gemfile +5 -0
- data/gemfiles/rails_edge/Gemfile +13 -0
- data/lib/formtastic/action_class_finder.rb +18 -0
- data/lib/formtastic/actions/button_action.rb +55 -60
- data/lib/formtastic/actions/input_action.rb +59 -57
- data/lib/formtastic/actions/link_action.rb +68 -67
- data/lib/formtastic/actions.rb +6 -3
- data/lib/formtastic/deprecation.rb +5 -0
- data/lib/formtastic/engine.rb +3 -1
- data/lib/formtastic/form_builder.rb +35 -16
- data/lib/formtastic/helpers/action_helper.rb +34 -28
- data/lib/formtastic/helpers/enum.rb +13 -0
- data/lib/formtastic/helpers/errors_helper.rb +2 -2
- data/lib/formtastic/helpers/fieldset_wrapper.rb +16 -12
- data/lib/formtastic/helpers/form_helper.rb +19 -16
- data/lib/formtastic/helpers/input_helper.rb +69 -97
- data/lib/formtastic/helpers/inputs_helper.rb +35 -25
- data/lib/formtastic/helpers/reflection.rb +4 -4
- data/lib/formtastic/helpers.rb +1 -2
- data/lib/formtastic/html_attributes.rb +12 -1
- data/lib/formtastic/i18n.rb +1 -1
- data/lib/formtastic/input_class_finder.rb +18 -0
- data/lib/formtastic/inputs/base/choices.rb +2 -2
- data/lib/formtastic/inputs/base/collections.rb +46 -14
- data/lib/formtastic/inputs/base/database.rb +7 -2
- data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
- data/lib/formtastic/inputs/base/errors.rb +7 -7
- data/lib/formtastic/inputs/base/hints.rb +2 -2
- data/lib/formtastic/inputs/base/html.rb +10 -9
- data/lib/formtastic/inputs/base/labelling.rb +5 -8
- data/lib/formtastic/inputs/base/naming.rb +4 -4
- data/lib/formtastic/inputs/base/numeric.rb +1 -1
- data/lib/formtastic/inputs/base/options.rb +3 -4
- data/lib/formtastic/inputs/base/stringish.rb +10 -2
- data/lib/formtastic/inputs/base/timeish.rb +34 -22
- data/lib/formtastic/inputs/base/validations.rb +41 -13
- data/lib/formtastic/inputs/base/wrapping.rb +29 -26
- data/lib/formtastic/inputs/base.rb +22 -15
- data/lib/formtastic/inputs/boolean_input.rb +26 -12
- data/lib/formtastic/inputs/check_boxes_input.rb +39 -31
- data/lib/formtastic/inputs/color_input.rb +41 -0
- data/lib/formtastic/inputs/country_input.rb +24 -5
- data/lib/formtastic/inputs/datalist_input.rb +41 -0
- data/lib/formtastic/inputs/date_picker_input.rb +93 -0
- data/lib/formtastic/inputs/{date_input.rb → date_select_input.rb} +1 -1
- data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
- data/lib/formtastic/inputs/{datetime_input.rb → datetime_select_input.rb} +1 -1
- data/lib/formtastic/inputs/file_input.rb +2 -2
- data/lib/formtastic/inputs/hidden_input.rb +2 -6
- data/lib/formtastic/inputs/radio_input.rb +28 -22
- data/lib/formtastic/inputs/select_input.rb +36 -39
- data/lib/formtastic/inputs/time_picker_input.rb +99 -0
- data/lib/formtastic/inputs/{time_input.rb → time_select_input.rb} +6 -2
- data/lib/formtastic/inputs/time_zone_input.rb +16 -6
- data/lib/formtastic/inputs.rb +32 -21
- data/lib/formtastic/localized_string.rb +1 -1
- data/lib/formtastic/localizer.rb +24 -24
- data/lib/formtastic/namespaced_class_finder.rb +99 -0
- data/lib/formtastic/version.rb +1 -1
- data/lib/formtastic.rb +20 -10
- data/lib/generators/formtastic/form/form_generator.rb +10 -4
- data/lib/generators/formtastic/input/input_generator.rb +46 -0
- data/lib/generators/formtastic/install/install_generator.rb +5 -19
- data/lib/generators/templates/_form.html.slim +2 -2
- data/lib/generators/templates/formtastic.rb +46 -25
- data/lib/generators/templates/input.rb +19 -0
- data/sample/basic_inputs.html +23 -3
- data/script/integration-template.rb +74 -0
- data/script/integration.sh +19 -0
- data/spec/action_class_finder_spec.rb +12 -0
- data/spec/actions/button_action_spec.rb +8 -8
- data/spec/actions/generic_action_spec.rb +92 -56
- data/spec/actions/input_action_spec.rb +7 -7
- data/spec/actions/link_action_spec.rb +10 -10
- data/spec/builder/custom_builder_spec.rb +36 -20
- data/spec/builder/error_proc_spec.rb +4 -4
- data/spec/builder/semantic_fields_for_spec.rb +28 -29
- data/spec/fast_spec_helper.rb +12 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +45 -32
- data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
- data/spec/helpers/action_helper_spec.rb +75 -103
- data/spec/helpers/actions_helper_spec.rb +17 -17
- data/spec/helpers/form_helper_spec.rb +84 -33
- data/spec/helpers/input_helper_spec.rb +333 -285
- data/spec/helpers/inputs_helper_spec.rb +167 -121
- data/spec/helpers/reflection_helper_spec.rb +3 -3
- data/spec/helpers/semantic_errors_helper_spec.rb +23 -23
- data/spec/i18n_spec.rb +26 -26
- data/spec/input_class_finder_spec.rb +10 -0
- data/spec/inputs/base/collections_spec.rb +76 -0
- data/spec/inputs/base/validations_spec.rb +480 -0
- data/spec/inputs/boolean_input_spec.rb +100 -65
- data/spec/inputs/check_boxes_input_spec.rb +200 -101
- data/spec/inputs/color_input_spec.rb +85 -0
- data/spec/inputs/country_input_spec.rb +20 -20
- data/spec/inputs/custom_input_spec.rb +3 -4
- data/spec/inputs/datalist_input_spec.rb +61 -0
- data/spec/inputs/date_picker_input_spec.rb +449 -0
- data/spec/inputs/date_select_input_spec.rb +249 -0
- data/spec/inputs/datetime_picker_input_spec.rb +490 -0
- data/spec/inputs/datetime_select_input_spec.rb +209 -0
- data/spec/inputs/email_input_spec.rb +5 -5
- data/spec/inputs/file_input_spec.rb +6 -6
- data/spec/inputs/hidden_input_spec.rb +22 -35
- data/spec/inputs/include_blank_spec.rb +11 -11
- data/spec/inputs/label_spec.rb +62 -25
- data/spec/inputs/number_input_spec.rb +112 -112
- data/spec/inputs/password_input_spec.rb +5 -5
- data/spec/inputs/phone_input_spec.rb +5 -5
- data/spec/inputs/placeholder_spec.rb +6 -6
- data/spec/inputs/radio_input_spec.rb +99 -55
- data/spec/inputs/range_input_spec.rb +66 -66
- data/spec/inputs/readonly_spec.rb +50 -0
- data/spec/inputs/search_input_spec.rb +5 -5
- data/spec/inputs/select_input_spec.rb +170 -170
- data/spec/inputs/string_input_spec.rb +68 -16
- data/spec/inputs/text_input_spec.rb +16 -16
- data/spec/inputs/time_picker_input_spec.rb +455 -0
- data/spec/inputs/time_select_input_spec.rb +261 -0
- data/spec/inputs/time_zone_input_spec.rb +54 -28
- data/spec/inputs/url_input_spec.rb +5 -5
- data/spec/inputs/with_options_spec.rb +7 -7
- data/spec/localizer_spec.rb +39 -17
- data/spec/namespaced_class_finder_spec.rb +79 -0
- data/spec/schema.rb +21 -0
- data/spec/spec_helper.rb +254 -221
- data/spec/support/custom_macros.rb +128 -95
- data/spec/support/shared_examples.rb +12 -0
- data/spec/support/specialized_class_finder_shared_example.rb +27 -0
- data/spec/support/test_environment.rb +26 -10
- metadata +177 -238
- data/.travis.yml +0 -8
- data/Appraisals +0 -11
- data/CHANGELOG +0 -371
- data/gemfiles/rails-3.0.gemfile +0 -7
- data/gemfiles/rails-3.1.gemfile +0 -7
- data/gemfiles/rails-3.2.gemfile +0 -7
- data/lib/formtastic/helpers/buttons_helper.rb +0 -310
- data/lib/formtastic/inputs/base/grouped_collections.rb +0 -77
- data/lib/formtastic/util.rb +0 -25
- data/lib/tasks/verify_rcov.rb +0 -44
- data/spec/helpers/buttons_helper_spec.rb +0 -166
- data/spec/helpers/commit_button_helper_spec.rb +0 -530
- data/spec/inputs/date_input_spec.rb +0 -227
- data/spec/inputs/datetime_input_spec.rb +0 -185
- data/spec/inputs/time_input_spec.rb +0 -267
- data/spec/support/deferred_garbage_collection.rb +0 -21
|
@@ -1,31 +1,23 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
require 'spec_helper'
|
|
3
3
|
|
|
4
|
-
describe '
|
|
5
|
-
|
|
6
|
-
include FormtasticSpecHelper
|
|
4
|
+
RSpec.describe 'with input class finder' do
|
|
5
|
+
include_context 'form builder'
|
|
7
6
|
|
|
8
7
|
before do
|
|
9
|
-
@
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@errors = mock('errors')
|
|
13
|
-
@errors.stub!(:[]).and_return([])
|
|
14
|
-
@new_post.stub!(:errors).and_return(@errors)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
after do
|
|
18
|
-
::I18n.backend.reload!
|
|
8
|
+
@errors = double('errors')
|
|
9
|
+
allow(@errors).to receive(:[]).and_return([])
|
|
10
|
+
allow(@new_post).to receive(:errors).and_return(@errors)
|
|
19
11
|
end
|
|
20
12
|
|
|
21
13
|
describe 'arguments and options' do
|
|
22
14
|
|
|
23
15
|
it 'should require the first argument (the method on form\'s object)' do
|
|
24
|
-
|
|
16
|
+
expect {
|
|
25
17
|
concat(semantic_form_for(@new_post) do |builder|
|
|
26
18
|
concat(builder.input()) # no args passed in at all
|
|
27
19
|
end)
|
|
28
|
-
}.
|
|
20
|
+
}.to raise_error(ArgumentError)
|
|
29
21
|
end
|
|
30
22
|
|
|
31
23
|
describe ':required option' do
|
|
@@ -37,8 +29,8 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
37
29
|
concat(semantic_form_for(@new_post) do |builder|
|
|
38
30
|
concat(builder.input(:title, :required => true))
|
|
39
31
|
end)
|
|
40
|
-
output_buffer.
|
|
41
|
-
output_buffer.
|
|
32
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
33
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
42
34
|
end
|
|
43
35
|
end
|
|
44
36
|
|
|
@@ -47,7 +39,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
47
39
|
concat(semantic_form_for(@new_post) do |builder|
|
|
48
40
|
concat(builder.input(:title, :required => true))
|
|
49
41
|
end)
|
|
50
|
-
output_buffer.
|
|
42
|
+
expect(output_buffer).to have_tag('form li.required label', :text => /required yo/)
|
|
51
43
|
end
|
|
52
44
|
end
|
|
53
45
|
end
|
|
@@ -56,7 +48,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
56
48
|
|
|
57
49
|
before do
|
|
58
50
|
@string = Formtastic::FormBuilder.optional_string = " optional yo!" # ensure there's something in the string
|
|
59
|
-
@new_post.class.
|
|
51
|
+
expect(@new_post.class).not_to receive(:reflect_on_all_validations)
|
|
60
52
|
end
|
|
61
53
|
|
|
62
54
|
after do
|
|
@@ -67,26 +59,26 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
67
59
|
concat(semantic_form_for(@new_post) do |builder|
|
|
68
60
|
concat(builder.input(:title, :required => false))
|
|
69
61
|
end)
|
|
70
|
-
output_buffer.
|
|
71
|
-
output_buffer.
|
|
62
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
63
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
72
64
|
end
|
|
73
65
|
|
|
74
66
|
it 'should set and "optional" class also when there is presence validator' do
|
|
75
|
-
@new_post.class.
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
68
|
+
active_model_presence_validator([:title])
|
|
69
|
+
])
|
|
78
70
|
concat(semantic_form_for(@new_post) do |builder|
|
|
79
71
|
concat(builder.input(:title, :required => false))
|
|
80
72
|
end)
|
|
81
|
-
output_buffer.
|
|
82
|
-
output_buffer.
|
|
73
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
74
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
83
75
|
end
|
|
84
76
|
|
|
85
77
|
it 'should append the "optional" string to the label' do
|
|
86
78
|
concat(semantic_form_for(@new_post) do |builder|
|
|
87
79
|
concat(builder.input(:title, :required => false))
|
|
88
80
|
end)
|
|
89
|
-
output_buffer.
|
|
81
|
+
expect(output_buffer).to have_tag('form li.optional label', :text => /#{@string}$/)
|
|
90
82
|
end
|
|
91
83
|
|
|
92
84
|
end
|
|
@@ -96,14 +88,14 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
96
88
|
describe 'and an object was not given' do
|
|
97
89
|
|
|
98
90
|
it 'should use the default value' do
|
|
99
|
-
Formtastic::FormBuilder.all_fields_required_by_default.
|
|
91
|
+
expect(Formtastic::FormBuilder.all_fields_required_by_default).to eq(true)
|
|
100
92
|
Formtastic::FormBuilder.all_fields_required_by_default = false
|
|
101
93
|
|
|
102
94
|
concat(semantic_form_for(:project, :url => 'http://test.host/') do |builder|
|
|
103
95
|
concat(builder.input(:title))
|
|
104
96
|
end)
|
|
105
|
-
output_buffer.
|
|
106
|
-
output_buffer.
|
|
97
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
98
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
107
99
|
|
|
108
100
|
Formtastic::FormBuilder.all_fields_required_by_default = true
|
|
109
101
|
end
|
|
@@ -112,90 +104,151 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
112
104
|
|
|
113
105
|
describe 'and an object with :validators_on was given (ActiveModel, Active Resource)' do
|
|
114
106
|
before do
|
|
115
|
-
@new_post.
|
|
107
|
+
allow(@new_post).to receive(:class).and_return(::PostModel)
|
|
116
108
|
end
|
|
117
109
|
|
|
118
110
|
after do
|
|
119
|
-
@new_post.
|
|
111
|
+
allow(@new_post).to receive(:class).and_return(::Post)
|
|
120
112
|
end
|
|
121
113
|
describe 'and validates_presence_of was called for the method' do
|
|
122
114
|
it 'should be required' do
|
|
123
115
|
|
|
124
|
-
@new_post.class.
|
|
125
|
-
|
|
126
|
-
|
|
116
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
117
|
+
active_model_presence_validator([:title])
|
|
118
|
+
])
|
|
127
119
|
|
|
128
|
-
@new_post.class.
|
|
129
|
-
|
|
130
|
-
|
|
120
|
+
expect(@new_post.class).to receive(:validators_on).with(:body).at_least(:once).and_return([
|
|
121
|
+
active_model_presence_validator([:body], {:if => true})
|
|
122
|
+
])
|
|
131
123
|
|
|
132
124
|
concat(semantic_form_for(@new_post) do |builder|
|
|
133
125
|
concat(builder.input(:title))
|
|
134
126
|
concat(builder.input(:body))
|
|
135
127
|
end)
|
|
136
|
-
output_buffer.
|
|
137
|
-
output_buffer.
|
|
128
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
129
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
138
130
|
end
|
|
139
131
|
|
|
140
132
|
it 'should be required when there is :on => :create option on create' do
|
|
141
133
|
with_config :required_string, " required yo!" do
|
|
142
|
-
@new_post.class.
|
|
143
|
-
|
|
144
|
-
|
|
134
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
135
|
+
active_model_presence_validator([:title], {:on => :create})
|
|
136
|
+
])
|
|
137
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
138
|
+
concat(builder.input(:title))
|
|
139
|
+
end)
|
|
140
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
141
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'should be required when there is :create option in validation contexts array on create' do
|
|
146
|
+
with_config :required_string, " required yo!" do
|
|
147
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
148
|
+
active_model_presence_validator([:title], {:on => [:create]})
|
|
149
|
+
])
|
|
145
150
|
concat(semantic_form_for(@new_post) do |builder|
|
|
146
151
|
concat(builder.input(:title))
|
|
147
152
|
end)
|
|
148
|
-
output_buffer.
|
|
149
|
-
output_buffer.
|
|
153
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
154
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
150
155
|
end
|
|
151
156
|
end
|
|
152
157
|
|
|
153
158
|
it 'should be required when there is :on => :save option on create' do
|
|
154
159
|
with_config :required_string, " required yo!" do
|
|
155
|
-
@new_post.class.
|
|
156
|
-
|
|
157
|
-
|
|
160
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
161
|
+
active_model_presence_validator([:title], {:on => :save})
|
|
162
|
+
])
|
|
158
163
|
concat(semantic_form_for(@new_post) do |builder|
|
|
159
164
|
concat(builder.input(:title))
|
|
160
165
|
end)
|
|
161
|
-
output_buffer.
|
|
162
|
-
output_buffer.
|
|
166
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
167
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'should be required when there is :save option in validation contexts array on create' do
|
|
172
|
+
with_config :required_string, " required yo!" do
|
|
173
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
174
|
+
active_model_presence_validator([:title], {:on => [:save]})
|
|
175
|
+
])
|
|
176
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
177
|
+
concat(builder.input(:title))
|
|
178
|
+
end)
|
|
179
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
180
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
163
181
|
end
|
|
164
182
|
end
|
|
165
183
|
|
|
166
184
|
it 'should be required when there is :on => :save option on update' do
|
|
167
185
|
with_config :required_string, " required yo!" do
|
|
168
|
-
@fred.class.
|
|
169
|
-
|
|
170
|
-
|
|
186
|
+
expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
|
|
187
|
+
active_model_presence_validator([:login], {:on => :save})
|
|
188
|
+
])
|
|
189
|
+
concat(semantic_form_for(@fred) do |builder|
|
|
190
|
+
concat(builder.input(:login))
|
|
191
|
+
end)
|
|
192
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
193
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it 'should be required when there is :save option in validation contexts array on update' do
|
|
198
|
+
with_config :required_string, " required yo!" do
|
|
199
|
+
expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
|
|
200
|
+
active_model_presence_validator([:login], {:on => [:save]})
|
|
201
|
+
])
|
|
171
202
|
concat(semantic_form_for(@fred) do |builder|
|
|
172
203
|
concat(builder.input(:login))
|
|
173
204
|
end)
|
|
174
|
-
output_buffer.
|
|
175
|
-
output_buffer.
|
|
205
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
206
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
176
207
|
end
|
|
177
208
|
end
|
|
178
209
|
|
|
179
210
|
it 'should not be required when there is :on => :create option on update' do
|
|
180
|
-
@fred.class.
|
|
181
|
-
|
|
182
|
-
|
|
211
|
+
expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
|
|
212
|
+
active_model_presence_validator([:login], {:on => :create})
|
|
213
|
+
])
|
|
214
|
+
concat(semantic_form_for(@fred) do |builder|
|
|
215
|
+
concat(builder.input(:login))
|
|
216
|
+
end)
|
|
217
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
218
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it 'should not be required when there is :create option in validation contexts array on update' do
|
|
222
|
+
expect(@fred.class).to receive(:validators_on).with(:login).at_least(:once).and_return([
|
|
223
|
+
active_model_presence_validator([:login], {:on => [:create]})
|
|
224
|
+
])
|
|
183
225
|
concat(semantic_form_for(@fred) do |builder|
|
|
184
226
|
concat(builder.input(:login))
|
|
185
227
|
end)
|
|
186
|
-
output_buffer.
|
|
187
|
-
output_buffer.
|
|
228
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
229
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
188
230
|
end
|
|
189
231
|
|
|
190
232
|
it 'should not be required when there is :on => :update option on create' do
|
|
191
|
-
@new_post.class.
|
|
192
|
-
|
|
193
|
-
|
|
233
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
234
|
+
active_model_presence_validator([:title], {:on => :update})
|
|
235
|
+
])
|
|
236
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
237
|
+
concat(builder.input(:title))
|
|
238
|
+
end)
|
|
239
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
240
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it 'should not be required when there is :update option in validation contexts array on create' do
|
|
244
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).at_least(:once).and_return([
|
|
245
|
+
active_model_presence_validator([:title], {:on => [:update]})
|
|
246
|
+
])
|
|
194
247
|
concat(semantic_form_for(@new_post) do |builder|
|
|
195
248
|
concat(builder.input(:title))
|
|
196
249
|
end)
|
|
197
|
-
output_buffer.
|
|
198
|
-
output_buffer.
|
|
250
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
251
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
199
252
|
end
|
|
200
253
|
|
|
201
254
|
it 'should be not be required if the optional :if condition is not satisifed' do
|
|
@@ -219,38 +272,38 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
219
272
|
end
|
|
220
273
|
|
|
221
274
|
it 'should be required if the optional :if with a method string evaluates to true' do
|
|
222
|
-
@new_post.
|
|
275
|
+
expect(@new_post).to receive(:required_condition).and_return(true)
|
|
223
276
|
presence_should_be_required(:required => true, :tag => :body, :options => { :if => :required_condition })
|
|
224
277
|
end
|
|
225
278
|
|
|
226
279
|
it 'should be required if the optional :if with a method string evaluates to false' do
|
|
227
|
-
@new_post.
|
|
280
|
+
expect(@new_post).to receive(:required_condition).and_return(false)
|
|
228
281
|
presence_should_be_required(:required => false, :tag => :body, :options => { :if => :required_condition })
|
|
229
282
|
end
|
|
230
283
|
|
|
231
284
|
it 'should be required if the optional :unless with a method string evaluates to false' do
|
|
232
|
-
|
|
285
|
+
expect(@new_post).to receive(:required_condition).and_return(false)
|
|
233
286
|
presence_should_be_required(:required => true, :tag => :body, :options => { :unless => :required_condition })
|
|
234
287
|
end
|
|
235
288
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
289
|
+
it 'should not be required if the optional :unless with a method string evaluates to true' do
|
|
290
|
+
expect(@new_post).to receive(:required_condition).and_return(true)
|
|
291
|
+
presence_should_be_required(:required => false, :tag => :body, :options => { :unless => :required_condition })
|
|
292
|
+
end
|
|
240
293
|
end
|
|
241
294
|
|
|
242
295
|
describe 'and validates_inclusion_of was called for the method' do
|
|
243
296
|
it 'should be required' do
|
|
244
|
-
@new_post.class.
|
|
245
|
-
|
|
246
|
-
|
|
297
|
+
expect(@new_post.class).to receive(:validators_on).with(:published).at_least(:once).and_return([
|
|
298
|
+
active_model_inclusion_validator([:published], {:in => [false, true]})
|
|
299
|
+
])
|
|
247
300
|
should_be_required(:tag => :published, :required => true)
|
|
248
301
|
end
|
|
249
302
|
|
|
250
303
|
it 'should not be required if allow_blank is true' do
|
|
251
|
-
@new_post.class.
|
|
252
|
-
|
|
253
|
-
|
|
304
|
+
expect(@new_post.class).to receive(:validators_on).with(:published).at_least(:once).and_return([
|
|
305
|
+
active_model_inclusion_validator([:published], {:in => [false, true], :allow_blank => true})
|
|
306
|
+
])
|
|
254
307
|
should_be_required(:tag => :published, :required => false)
|
|
255
308
|
end
|
|
256
309
|
end
|
|
@@ -282,14 +335,14 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
282
335
|
end
|
|
283
336
|
|
|
284
337
|
def add_presence_validator(options)
|
|
285
|
-
@new_post.class.
|
|
286
|
-
|
|
287
|
-
|
|
338
|
+
allow(@new_post.class).to receive(:validators_on).with(options[:tag]).and_return([
|
|
339
|
+
active_model_presence_validator([options[:tag]], options[:options])
|
|
340
|
+
])
|
|
288
341
|
end
|
|
289
342
|
|
|
290
343
|
def add_length_validator(options)
|
|
291
|
-
@new_post.class.
|
|
292
|
-
|
|
344
|
+
expect(@new_post.class).to receive(:validators_on).with(options[:tag]).at_least(:once) {[
|
|
345
|
+
active_model_length_validator([options[:tag]], options[:options])
|
|
293
346
|
]}
|
|
294
347
|
end
|
|
295
348
|
|
|
@@ -300,11 +353,11 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
300
353
|
end)
|
|
301
354
|
|
|
302
355
|
if options[:required]
|
|
303
|
-
output_buffer.
|
|
304
|
-
output_buffer.
|
|
356
|
+
expect(output_buffer).not_to have_tag('form li.optional')
|
|
357
|
+
expect(output_buffer).to have_tag('form li.required')
|
|
305
358
|
else
|
|
306
|
-
output_buffer.
|
|
307
|
-
output_buffer.
|
|
359
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
360
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
308
361
|
end
|
|
309
362
|
end
|
|
310
363
|
|
|
@@ -321,15 +374,15 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
321
374
|
# TODO JF reversed this during refactor, need to make sure
|
|
322
375
|
describe 'and there are no requirement validations on the method' do
|
|
323
376
|
before do
|
|
324
|
-
@new_post.class.
|
|
377
|
+
expect(@new_post.class).to receive(:validators_on).with(:title).and_return([])
|
|
325
378
|
end
|
|
326
379
|
|
|
327
380
|
it 'should not be required' do
|
|
328
381
|
concat(semantic_form_for(@new_post) do |builder|
|
|
329
382
|
concat(builder.input(:title))
|
|
330
383
|
end)
|
|
331
|
-
output_buffer.
|
|
332
|
-
output_buffer.
|
|
384
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
385
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
333
386
|
end
|
|
334
387
|
end
|
|
335
388
|
|
|
@@ -337,21 +390,21 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
337
390
|
|
|
338
391
|
describe 'and an object without :validators_on' do
|
|
339
392
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
concat(semantic_form_for(@new_post) do |builder|
|
|
345
|
-
concat(builder.input(:title))
|
|
346
|
-
end)
|
|
347
|
-
output_buffer.should_not have_tag('form li.required')
|
|
348
|
-
output_buffer.should have_tag('form li.optional')
|
|
393
|
+
it 'should use the default value' do
|
|
394
|
+
expect(Formtastic::FormBuilder.all_fields_required_by_default).to eq(true)
|
|
395
|
+
Formtastic::FormBuilder.all_fields_required_by_default = false
|
|
349
396
|
|
|
350
|
-
|
|
351
|
-
|
|
397
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
398
|
+
concat(builder.input(:title))
|
|
399
|
+
end)
|
|
400
|
+
expect(output_buffer).not_to have_tag('form li.required')
|
|
401
|
+
expect(output_buffer).to have_tag('form li.optional')
|
|
352
402
|
|
|
403
|
+
Formtastic::FormBuilder.all_fields_required_by_default = true
|
|
353
404
|
end
|
|
354
405
|
|
|
406
|
+
end
|
|
407
|
+
|
|
355
408
|
end
|
|
356
409
|
|
|
357
410
|
end
|
|
@@ -364,7 +417,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
364
417
|
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
|
365
418
|
concat(builder.input(:anything))
|
|
366
419
|
end)
|
|
367
|
-
output_buffer.
|
|
420
|
+
expect(output_buffer).to have_tag('form li.string')
|
|
368
421
|
end
|
|
369
422
|
|
|
370
423
|
it 'should default to password for forms without objects if column is password' do
|
|
@@ -373,117 +426,145 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
373
426
|
concat(builder.input(:password_confirmation))
|
|
374
427
|
concat(builder.input(:confirm_password))
|
|
375
428
|
end)
|
|
376
|
-
output_buffer.
|
|
429
|
+
expect(output_buffer).to have_tag('form li.password', :count => 3)
|
|
377
430
|
end
|
|
378
431
|
|
|
379
432
|
it 'should default to a string for methods on objects that don\'t respond to "column_for_attribute"' do
|
|
380
|
-
@new_post.
|
|
381
|
-
@new_post.
|
|
382
|
-
default_input_type(nil, :method_without_a_database_column).
|
|
433
|
+
allow(@new_post).to receive(:method_without_a_database_column)
|
|
434
|
+
allow(@new_post).to receive(:column_for_attribute).and_return(nil)
|
|
435
|
+
expect(default_input_type(nil, :method_without_a_database_column)).to eq(:string)
|
|
383
436
|
end
|
|
384
437
|
|
|
385
438
|
it 'should default to :password for methods that don\'t have a column in the database but "password" is in the method name' do
|
|
386
|
-
@new_post.
|
|
387
|
-
@new_post.
|
|
388
|
-
default_input_type(nil, :password_method_without_a_database_column).
|
|
439
|
+
allow(@new_post).to receive(:password_method_without_a_database_column)
|
|
440
|
+
allow(@new_post).to receive(:column_for_attribute).and_return(nil)
|
|
441
|
+
expect(default_input_type(nil, :password_method_without_a_database_column)).to eq(:password)
|
|
389
442
|
end
|
|
390
443
|
|
|
391
444
|
it 'should default to :password for methods on objects that don\'t respond to "column_for_attribute" but "password" is in the method name' do
|
|
392
|
-
@new_post.
|
|
393
|
-
@new_post.
|
|
394
|
-
default_input_type(nil, :password_method_without_a_database_column).
|
|
445
|
+
allow(@new_post).to receive(:password_method_without_a_database_column)
|
|
446
|
+
allow(@new_post).to receive(:column_for_attribute).and_return(nil)
|
|
447
|
+
expect(default_input_type(nil, :password_method_without_a_database_column)).to eq(:password)
|
|
395
448
|
end
|
|
396
449
|
|
|
397
450
|
it 'should default to :number for "integer" column with name ending in "_id"' do
|
|
398
|
-
@new_post.
|
|
399
|
-
@new_post.
|
|
400
|
-
default_input_type(:integer, :aws_instance_id).
|
|
451
|
+
allow(@new_post).to receive(:aws_instance_id)
|
|
452
|
+
allow(@new_post).to receive(:column_for_attribute).with(:aws_instance_id).and_return(double('column', :type => :integer))
|
|
453
|
+
expect(default_input_type(:integer, :aws_instance_id)).to eq(:number)
|
|
401
454
|
end
|
|
402
455
|
|
|
403
456
|
it 'should default to :select for associations' do
|
|
404
|
-
@new_post.class.
|
|
405
|
-
@new_post.class.
|
|
406
|
-
default_input_type(:integer, :user_id).
|
|
407
|
-
default_input_type(:integer, :section_id).
|
|
457
|
+
allow(@new_post.class).to receive(:reflect_on_association).with(:user_id).and_return(double('ActiveRecord::Reflection::AssociationReflection'))
|
|
458
|
+
allow(@new_post.class).to receive(:reflect_on_association).with(:section_id).and_return(double('ActiveRecord::Reflection::AssociationReflection'))
|
|
459
|
+
expect(default_input_type(:integer, :user_id)).to eq(:select)
|
|
460
|
+
expect(default_input_type(:integer, :section_id)).to eq(:select)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it 'should default to :select for enum' do
|
|
464
|
+
statuses = ActiveSupport::HashWithIndifferentAccess.new("active"=>0, "inactive"=>1)
|
|
465
|
+
allow(@new_post.class).to receive(:statuses) { statuses }
|
|
466
|
+
allow(@new_post).to receive(:defined_enums) { {"status" => statuses } }
|
|
467
|
+
|
|
468
|
+
expect(default_input_type(:integer, :status)).to eq(:select)
|
|
408
469
|
end
|
|
409
470
|
|
|
410
471
|
it 'should default to :password for :string column types with "password" in the method name' do
|
|
411
|
-
default_input_type(:string, :password).
|
|
412
|
-
default_input_type(:string, :hashed_password).
|
|
413
|
-
default_input_type(:string, :password_hash).
|
|
472
|
+
expect(default_input_type(:string, :password)).to eq(:password)
|
|
473
|
+
expect(default_input_type(:string, :hashed_password)).to eq(:password)
|
|
474
|
+
expect(default_input_type(:string, :password_hash)).to eq(:password)
|
|
414
475
|
end
|
|
415
476
|
|
|
416
477
|
it 'should default to :text for :text column types' do
|
|
417
|
-
default_input_type(:text).
|
|
478
|
+
expect(default_input_type(:text)).to eq(:text)
|
|
418
479
|
end
|
|
419
480
|
|
|
420
|
-
it 'should default to :
|
|
421
|
-
default_input_type(:date).
|
|
481
|
+
it 'should default to :date_select for :date column types' do
|
|
482
|
+
expect(default_input_type(:date)).to eq(:date_select)
|
|
422
483
|
end
|
|
423
484
|
|
|
424
|
-
it 'should default to :
|
|
425
|
-
default_input_type(:
|
|
426
|
-
default_input_type(:
|
|
485
|
+
it 'should default to :text for :hstore, :json and :jsonb column types' do
|
|
486
|
+
expect(default_input_type(:hstore)).to eq(:text)
|
|
487
|
+
expect(default_input_type(:json)).to eq(:text)
|
|
488
|
+
expect(default_input_type(:jsonb)).to eq(:text)
|
|
427
489
|
end
|
|
428
490
|
|
|
429
|
-
it 'should default to :
|
|
430
|
-
default_input_type(:
|
|
491
|
+
it 'should default to :datetime_select for :datetime and :timestamp column types' do
|
|
492
|
+
expect(default_input_type(:datetime)).to eq(:datetime_select)
|
|
493
|
+
expect(default_input_type(:timestamp)).to eq(:datetime_select)
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
it 'should default to :time_select for :time column types' do
|
|
497
|
+
expect(default_input_type(:time)).to eq(:time_select)
|
|
431
498
|
end
|
|
432
499
|
|
|
433
500
|
it 'should default to :boolean for :boolean column types' do
|
|
434
|
-
default_input_type(:boolean).
|
|
501
|
+
expect(default_input_type(:boolean)).to eq(:boolean)
|
|
435
502
|
end
|
|
436
503
|
|
|
437
504
|
it 'should default to :string for :string column types' do
|
|
438
|
-
default_input_type(:string).
|
|
505
|
+
expect(default_input_type(:string)).to eq(:string)
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
it 'should default to :string for :citext column types' do
|
|
509
|
+
expect(default_input_type(:citext)).to eq(:string)
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
it 'should default to :string for :inet column types' do
|
|
513
|
+
expect(default_input_type(:inet)).to eq(:string)
|
|
439
514
|
end
|
|
440
515
|
|
|
441
516
|
it 'should default to :number for :integer, :float and :decimal column types' do
|
|
442
|
-
default_input_type(:integer).
|
|
443
|
-
default_input_type(:float).
|
|
444
|
-
default_input_type(:decimal).
|
|
517
|
+
expect(default_input_type(:integer)).to eq(:number)
|
|
518
|
+
expect(default_input_type(:float)).to eq(:number)
|
|
519
|
+
expect(default_input_type(:decimal)).to eq(:number)
|
|
445
520
|
end
|
|
446
521
|
|
|
447
522
|
it 'should default to :country for :string columns named country' do
|
|
448
|
-
default_input_type(:string, :country).
|
|
523
|
+
expect(default_input_type(:string, :country)).to eq(:country)
|
|
449
524
|
end
|
|
450
525
|
|
|
451
526
|
it 'should default to :email for :string columns matching email' do
|
|
452
|
-
default_input_type(:string, :email).
|
|
453
|
-
default_input_type(:string, :customer_email).
|
|
454
|
-
default_input_type(:string, :email_work).
|
|
527
|
+
expect(default_input_type(:string, :email)).to eq(:email)
|
|
528
|
+
expect(default_input_type(:string, :customer_email)).to eq(:email)
|
|
529
|
+
expect(default_input_type(:string, :email_work)).to eq(:email)
|
|
455
530
|
end
|
|
456
531
|
|
|
457
532
|
it 'should default to :url for :string columns named url or website' do
|
|
458
|
-
default_input_type(:string, :url).
|
|
459
|
-
default_input_type(:string, :website).
|
|
460
|
-
default_input_type(:string, :my_url).
|
|
461
|
-
default_input_type(:string, :hurl).
|
|
533
|
+
expect(default_input_type(:string, :url)).to eq(:url)
|
|
534
|
+
expect(default_input_type(:string, :website)).to eq(:url)
|
|
535
|
+
expect(default_input_type(:string, :my_url)).to eq(:url)
|
|
536
|
+
expect(default_input_type(:string, :hurl)).not_to eq(:url)
|
|
462
537
|
end
|
|
463
538
|
|
|
464
539
|
it 'should default to :phone for :string columns named phone or fax' do
|
|
465
|
-
default_input_type(:string, :phone).
|
|
466
|
-
default_input_type(:string, :fax).
|
|
540
|
+
expect(default_input_type(:string, :phone)).to eq(:phone)
|
|
541
|
+
expect(default_input_type(:string, :fax)).to eq(:phone)
|
|
467
542
|
end
|
|
468
543
|
|
|
469
544
|
it 'should default to :search for :string columns named search' do
|
|
470
|
-
default_input_type(:string, :search).
|
|
545
|
+
expect(default_input_type(:string, :search)).to eq(:search)
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
it 'should default to :color for :string columns matching color' do
|
|
549
|
+
expect(default_input_type(:string, :color)).to eq(:color)
|
|
550
|
+
expect(default_input_type(:string, :user_color)).to eq(:color)
|
|
551
|
+
expect(default_input_type(:string, :color_for_image)).to eq(:color)
|
|
471
552
|
end
|
|
472
553
|
|
|
473
554
|
describe 'defaulting to file column' do
|
|
474
555
|
Formtastic::FormBuilder.file_methods.each do |method|
|
|
475
556
|
it "should default to :file for attributes that respond to ##{method}" do
|
|
476
|
-
column =
|
|
557
|
+
column = double('column')
|
|
477
558
|
|
|
478
559
|
Formtastic::FormBuilder.file_methods.each do |test|
|
|
479
560
|
### TODO: Check if this is ok
|
|
480
|
-
column.
|
|
561
|
+
allow(column).to receive(method).with(test).and_return(method == test)
|
|
481
562
|
end
|
|
482
563
|
|
|
483
|
-
@new_post.
|
|
564
|
+
expect(@new_post).to receive(method).and_return(column)
|
|
484
565
|
|
|
485
566
|
semantic_form_for(@new_post) do |builder|
|
|
486
|
-
builder.send(:default_input_type, method).
|
|
567
|
+
expect(builder.send(:default_input_type, method)).to eq(:file)
|
|
487
568
|
end
|
|
488
569
|
end
|
|
489
570
|
end
|
|
@@ -492,16 +573,16 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
492
573
|
end
|
|
493
574
|
|
|
494
575
|
it 'should call the corresponding input class with .to_html' do
|
|
495
|
-
[:select, :time_zone, :radio, :
|
|
496
|
-
@new_post.
|
|
497
|
-
@new_post.
|
|
576
|
+
[:select, :time_zone, :radio, :date_select, :datetime_select, :time_select, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
|
|
577
|
+
allow(@new_post).to receive(:generic_column_name)
|
|
578
|
+
allow(@new_post).to receive(:column_for_attribute).and_return(double('column', :type => :string, :limit => 255))
|
|
498
579
|
semantic_form_for(@new_post) do |builder|
|
|
499
|
-
input_instance =
|
|
580
|
+
input_instance = double('Input instance')
|
|
500
581
|
input_class = "#{input_style.to_s}_input".classify
|
|
501
582
|
input_constant = "Formtastic::Inputs::#{input_class}".constantize
|
|
502
583
|
|
|
503
|
-
input_constant.
|
|
504
|
-
input_instance.
|
|
584
|
+
expect(input_constant).to receive(:new).and_return(input_instance)
|
|
585
|
+
expect(input_instance).to receive(:to_html).and_return("some HTML")
|
|
505
586
|
|
|
506
587
|
concat(builder.input(:generic_column_name, :as => input_style))
|
|
507
588
|
end
|
|
@@ -517,21 +598,21 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
517
598
|
concat(semantic_form_for(@new_post) do |builder|
|
|
518
599
|
concat(builder.input(:title, :label => "Kustom"))
|
|
519
600
|
end)
|
|
520
|
-
output_buffer.
|
|
601
|
+
expect(output_buffer).to have_tag("form li label", :text => /Kustom/)
|
|
521
602
|
end
|
|
522
603
|
|
|
523
604
|
it 'should not generate a label if false' do
|
|
524
605
|
concat(semantic_form_for(@new_post) do |builder|
|
|
525
606
|
concat(builder.input(:title, :label => false))
|
|
526
607
|
end)
|
|
527
|
-
output_buffer.
|
|
608
|
+
expect(output_buffer).not_to have_tag("form li label")
|
|
528
609
|
end
|
|
529
610
|
|
|
530
611
|
it 'should be dupped if frozen' do
|
|
531
612
|
concat(semantic_form_for(@new_post) do |builder|
|
|
532
613
|
concat(builder.input(:title, :label => "Kustom".freeze))
|
|
533
614
|
end)
|
|
534
|
-
output_buffer.
|
|
615
|
+
expect(output_buffer).to have_tag("form li label", :text => /Kustom/)
|
|
535
616
|
end
|
|
536
617
|
end
|
|
537
618
|
|
|
@@ -542,18 +623,18 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
542
623
|
it 'should render a label with localized text and not apply the label_str_method' do
|
|
543
624
|
with_config :label_str_method, :reverse do
|
|
544
625
|
@localized_label_text = 'Localized title'
|
|
545
|
-
@new_post.
|
|
626
|
+
allow(@new_post).to receive(:meta_description)
|
|
546
627
|
::I18n.backend.store_translations :en,
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
628
|
+
:formtastic => {
|
|
629
|
+
:labels => {
|
|
630
|
+
:meta_description => @localized_label_text
|
|
631
|
+
}
|
|
632
|
+
}
|
|
552
633
|
|
|
553
634
|
concat(semantic_form_for(@new_post) do |builder|
|
|
554
635
|
concat(builder.input(:meta_description))
|
|
555
636
|
end)
|
|
556
|
-
output_buffer.
|
|
637
|
+
expect(output_buffer).to have_tag('form li label', :text => /Localized title/)
|
|
557
638
|
end
|
|
558
639
|
end
|
|
559
640
|
end
|
|
@@ -568,32 +649,32 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
568
649
|
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
|
569
650
|
concat(builder.input(:meta_description))
|
|
570
651
|
end)
|
|
571
|
-
output_buffer.
|
|
652
|
+
expect(output_buffer).to have_tag("form li label", :text => /#{'meta_description'.humanize}/)
|
|
572
653
|
end
|
|
573
654
|
end
|
|
574
655
|
end
|
|
575
656
|
|
|
576
657
|
describe 'and object is given' do
|
|
577
658
|
it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
|
|
578
|
-
@new_post.
|
|
579
|
-
@new_post.class.
|
|
659
|
+
allow(@new_post).to receive(:meta_description) # a two word method name
|
|
660
|
+
expect(@new_post.class).to receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
|
|
580
661
|
|
|
581
662
|
concat(semantic_form_for(@new_post) do |builder|
|
|
582
663
|
concat(builder.input(:meta_description))
|
|
583
664
|
end)
|
|
584
|
-
output_buffer.
|
|
665
|
+
expect(output_buffer).to have_tag("form li label", :text => /#{'meta_description'.humanize}/)
|
|
585
666
|
end
|
|
586
667
|
end
|
|
587
668
|
|
|
588
669
|
describe 'and object is given with label_str_method set to :capitalize' do
|
|
589
670
|
it 'should capitalize method name, passing it down to the label tag' do
|
|
590
671
|
with_config :label_str_method, :capitalize do
|
|
591
|
-
@new_post.
|
|
672
|
+
allow(@new_post).to receive(:meta_description)
|
|
592
673
|
|
|
593
674
|
concat(semantic_form_for(@new_post) do |builder|
|
|
594
675
|
concat(builder.input(:meta_description))
|
|
595
676
|
end)
|
|
596
|
-
output_buffer.
|
|
677
|
+
expect(output_buffer).to have_tag("form li label", :text => /#{'meta_description'.capitalize}/)
|
|
597
678
|
end
|
|
598
679
|
end
|
|
599
680
|
end
|
|
@@ -604,16 +685,16 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
604
685
|
@localized_label_text = 'Localized title'
|
|
605
686
|
@default_localized_label_text = 'Default localized title'
|
|
606
687
|
::I18n.backend.store_translations :en,
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
688
|
+
:formtastic => {
|
|
689
|
+
:labels => {
|
|
690
|
+
:title => @default_localized_label_text,
|
|
691
|
+
:published => @default_localized_label_text,
|
|
692
|
+
:post => {
|
|
693
|
+
:title => @localized_label_text,
|
|
694
|
+
:published => @default_localized_label_text
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
617
698
|
end
|
|
618
699
|
|
|
619
700
|
it 'should render a label with localized label (I18n)' do
|
|
@@ -622,26 +703,26 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
622
703
|
concat(builder.input(:title, :label => true))
|
|
623
704
|
concat(builder.input(:published, :as => :boolean, :label => true))
|
|
624
705
|
end)
|
|
625
|
-
output_buffer.
|
|
706
|
+
expect(output_buffer).to have_tag('form li label', :text => Regexp.new('^' + @localized_label_text))
|
|
626
707
|
end
|
|
627
708
|
end
|
|
628
709
|
|
|
629
710
|
it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
|
|
630
711
|
with_config :i18n_lookups_by_default, false do
|
|
631
712
|
::I18n.backend.store_translations :en,
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
713
|
+
:formtastic => {
|
|
714
|
+
:labels => {
|
|
715
|
+
:post => {
|
|
716
|
+
:title => nil,
|
|
717
|
+
:published => nil
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
640
721
|
concat(semantic_form_for(@new_post) do |builder|
|
|
641
722
|
concat(builder.input(:title, :label => true))
|
|
642
723
|
concat(builder.input(:published, :as => :boolean, :label => true))
|
|
643
724
|
end)
|
|
644
|
-
output_buffer.
|
|
725
|
+
expect(output_buffer).to have_tag('form li label', :text => Regexp.new('^' + @default_localized_label_text))
|
|
645
726
|
end
|
|
646
727
|
end
|
|
647
728
|
end
|
|
@@ -662,15 +743,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
662
743
|
concat(semantic_form_for(@new_post) do |builder|
|
|
663
744
|
concat(builder.input(:title, :hint => hint_text))
|
|
664
745
|
end)
|
|
665
|
-
output_buffer.
|
|
666
|
-
end
|
|
667
|
-
|
|
668
|
-
it 'should have a custom hint class if I ask for one' do
|
|
669
|
-
hint_text = "this is the title of the post"
|
|
670
|
-
concat(semantic_form_for(@new_post) do |builder|
|
|
671
|
-
concat(builder.input(:title, :hint => hint_text, :hint_class => 'custom-hint-class'))
|
|
672
|
-
end)
|
|
673
|
-
output_buffer.should have_tag("form li p.custom-hint-class", hint_text)
|
|
746
|
+
expect(output_buffer).to have_tag("form li p.inline-hints", :text => hint_text)
|
|
674
747
|
end
|
|
675
748
|
|
|
676
749
|
it 'should have a custom hint class defaulted for all forms' do
|
|
@@ -679,7 +752,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
679
752
|
concat(semantic_form_for(@new_post) do |builder|
|
|
680
753
|
concat(builder.input(:title, :hint => hint_text))
|
|
681
754
|
end)
|
|
682
|
-
output_buffer.
|
|
755
|
+
expect(output_buffer).to have_tag("form li p.custom-hint-class", :text => hint_text)
|
|
683
756
|
end
|
|
684
757
|
end
|
|
685
758
|
|
|
@@ -689,11 +762,11 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
689
762
|
@localized_hint_text = "This is the localized hint."
|
|
690
763
|
@default_localized_hint_text = "This is the default localized hint."
|
|
691
764
|
::I18n.backend.store_translations :en,
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
765
|
+
:formtastic => {
|
|
766
|
+
:hints => {
|
|
767
|
+
:title => @default_localized_hint_text,
|
|
768
|
+
}
|
|
769
|
+
}
|
|
697
770
|
end
|
|
698
771
|
|
|
699
772
|
after do
|
|
@@ -704,34 +777,17 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
704
777
|
it 'should render a hint paragraph containing a localized hint (I18n)' do
|
|
705
778
|
with_config :i18n_lookups_by_default, false do
|
|
706
779
|
::I18n.backend.store_translations :en,
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
780
|
+
:formtastic => {
|
|
781
|
+
:hints => {
|
|
782
|
+
:post => {
|
|
783
|
+
:title => @localized_hint_text
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
714
787
|
concat(semantic_form_for(@new_post) do |builder|
|
|
715
788
|
concat(builder.input(:title, :hint => true))
|
|
716
789
|
end)
|
|
717
|
-
output_buffer.
|
|
718
|
-
end
|
|
719
|
-
end
|
|
720
|
-
|
|
721
|
-
it 'should render a hint paragraph containing a localized hint (I18n) with a custom hint class if i ask for one' do
|
|
722
|
-
with_config :i18n_lookups_by_default, false do
|
|
723
|
-
::I18n.backend.store_translations :en,
|
|
724
|
-
:formtastic => {
|
|
725
|
-
:hints => {
|
|
726
|
-
:post => {
|
|
727
|
-
:title => @localized_hint_text
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
concat(semantic_form_for(@new_post) do |builder|
|
|
732
|
-
concat(builder.input(:title, :hint => true, :hint_class => 'custom-hint-class'))
|
|
733
|
-
end)
|
|
734
|
-
output_buffer.should have_tag('form li p.custom-hint-class', @localized_hint_text)
|
|
790
|
+
expect(output_buffer).to have_tag('form li p.inline-hints', :text => @localized_hint_text)
|
|
735
791
|
end
|
|
736
792
|
end
|
|
737
793
|
|
|
@@ -740,7 +796,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
740
796
|
concat(semantic_form_for(@new_post) do |builder|
|
|
741
797
|
concat(builder.input(:title, :hint => true))
|
|
742
798
|
end)
|
|
743
|
-
output_buffer.
|
|
799
|
+
expect(output_buffer).to have_tag('form li p.inline-hints', :text => @default_localized_hint_text)
|
|
744
800
|
end
|
|
745
801
|
end
|
|
746
802
|
end
|
|
@@ -751,7 +807,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
751
807
|
concat(semantic_form_for(@new_post) do |builder|
|
|
752
808
|
concat(builder.input(:title, :hint => false))
|
|
753
809
|
end)
|
|
754
|
-
output_buffer.
|
|
810
|
+
expect(output_buffer).not_to have_tag('form li p.inline-hints', :text => @localized_hint_text)
|
|
755
811
|
end
|
|
756
812
|
end
|
|
757
813
|
end
|
|
@@ -761,17 +817,17 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
761
817
|
it "should see the provided hash as a blank entry" do
|
|
762
818
|
with_config :i18n_lookups_by_default, false do
|
|
763
819
|
::I18n.backend.store_translations :en,
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
820
|
+
:formtastic => {
|
|
821
|
+
:hints => {
|
|
822
|
+
:title => { # movie title
|
|
823
|
+
:summary => @localized_hint_text # summary of movie
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
771
827
|
semantic_form_for(@new_post) do |builder|
|
|
772
828
|
concat(builder.input(:title, :hint => true))
|
|
773
829
|
end
|
|
774
|
-
output_buffer.
|
|
830
|
+
expect(output_buffer).not_to have_tag('form li p.inline-hints', :text => @localized_hint_text)
|
|
775
831
|
end
|
|
776
832
|
end
|
|
777
833
|
end
|
|
@@ -782,7 +838,7 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
782
838
|
concat(semantic_form_for(@new_post) do |builder|
|
|
783
839
|
concat(builder.input(:title))
|
|
784
840
|
end)
|
|
785
|
-
output_buffer.
|
|
841
|
+
expect(output_buffer).not_to have_tag('form li p.inline-hints')
|
|
786
842
|
end
|
|
787
843
|
end
|
|
788
844
|
end
|
|
@@ -797,25 +853,34 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
797
853
|
concat(semantic_form_for(@new_post) do |builder|
|
|
798
854
|
concat(builder.input(:title, :wrapper_html => {:id => :another_id}))
|
|
799
855
|
end)
|
|
800
|
-
output_buffer.
|
|
856
|
+
expect(output_buffer).to have_tag("form li#another_id")
|
|
801
857
|
end
|
|
802
858
|
|
|
803
859
|
it 'should append given classes to li default classes' do
|
|
804
860
|
concat(semantic_form_for(@new_post) do |builder|
|
|
805
861
|
concat(builder.input(:title, :wrapper_html => {:class => :another_class}, :required => true))
|
|
806
862
|
end)
|
|
807
|
-
output_buffer.
|
|
808
|
-
output_buffer.
|
|
809
|
-
output_buffer.
|
|
863
|
+
expect(output_buffer).to have_tag("form li.string")
|
|
864
|
+
expect(output_buffer).to have_tag("form li.required")
|
|
865
|
+
expect(output_buffer).to have_tag("form li.another_class")
|
|
810
866
|
end
|
|
811
867
|
|
|
812
868
|
it 'should allow classes to be an array' do
|
|
813
869
|
concat(semantic_form_for(@new_post) do |builder|
|
|
814
870
|
concat(builder.input(:title, :wrapper_html => {:class => [ :my_class, :another_class ]}))
|
|
815
871
|
end)
|
|
816
|
-
output_buffer.
|
|
817
|
-
output_buffer.
|
|
818
|
-
output_buffer.
|
|
872
|
+
expect(output_buffer).to have_tag("form li.string")
|
|
873
|
+
expect(output_buffer).to have_tag("form li.my_class")
|
|
874
|
+
expect(output_buffer).to have_tag("form li.another_class")
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
describe 'when nil' do
|
|
878
|
+
it 'should not put an id attribute on the div tag' do
|
|
879
|
+
concat(semantic_form_for(@new_post) do |builder|
|
|
880
|
+
concat(builder.input(:title, :wrapper_html => {:id => nil}))
|
|
881
|
+
end)
|
|
882
|
+
expect(output_buffer).to have_tag('form li:not([id])')
|
|
883
|
+
end
|
|
819
884
|
end
|
|
820
885
|
end
|
|
821
886
|
|
|
@@ -824,8 +889,8 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
824
889
|
concat(semantic_form_for(@new_post) do |builder|
|
|
825
890
|
concat(builder.input(:title))
|
|
826
891
|
end)
|
|
827
|
-
output_buffer.
|
|
828
|
-
output_buffer.
|
|
892
|
+
expect(output_buffer).to have_tag("form li#post_title_input")
|
|
893
|
+
expect(output_buffer).to have_tag("form li.string")
|
|
829
894
|
end
|
|
830
895
|
end
|
|
831
896
|
|
|
@@ -834,15 +899,15 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
834
899
|
describe ':collection option' do
|
|
835
900
|
|
|
836
901
|
it "should be required on polymorphic associations" do
|
|
837
|
-
@new_post.
|
|
838
|
-
@new_post.class.
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
@new_post.
|
|
842
|
-
|
|
902
|
+
allow(@new_post).to receive(:commentable)
|
|
903
|
+
allow(@new_post.class).to receive(:reflections).and_return({
|
|
904
|
+
:commentable => double('macro_reflection', :options => { :polymorphic => true }, :macro => :belongs_to)
|
|
905
|
+
})
|
|
906
|
+
allow(@new_post).to receive(:column_for_attribute).with(:commentable).and_return(
|
|
907
|
+
double('column', :type => :integer)
|
|
843
908
|
)
|
|
844
|
-
@new_post.class.
|
|
845
|
-
|
|
909
|
+
allow(@new_post.class).to receive(:reflect_on_association).with(:commentable).and_return(
|
|
910
|
+
double('reflection', :macro => :belongs_to, :options => { :polymorphic => true })
|
|
846
911
|
)
|
|
847
912
|
expect {
|
|
848
913
|
concat(semantic_form_for(@new_post) do |builder|
|
|
@@ -867,29 +932,26 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
867
932
|
concat(builder.input(:title, my_options))
|
|
868
933
|
concat(builder.input(:publish_at, my_options))
|
|
869
934
|
end)
|
|
870
|
-
output_buffer.
|
|
935
|
+
expect(output_buffer).to have_tag 'li.string', :count => 2
|
|
871
936
|
end
|
|
872
|
-
|
|
873
|
-
|
|
874
937
|
end
|
|
875
938
|
|
|
876
939
|
describe 'instantiating an input class' do
|
|
877
|
-
|
|
878
940
|
context 'when a class does not exist' do
|
|
879
941
|
it "should raise an error" do
|
|
880
|
-
|
|
942
|
+
expect {
|
|
881
943
|
concat(semantic_form_for(@new_post) do |builder|
|
|
882
944
|
builder.input(:title, :as => :non_existant)
|
|
883
945
|
end)
|
|
884
|
-
}.
|
|
946
|
+
}.to raise_error(Formtastic::UnknownInputError)
|
|
885
947
|
end
|
|
886
948
|
end
|
|
887
949
|
|
|
888
950
|
context 'when a customized top-level class does not exist' do
|
|
889
951
|
|
|
890
952
|
it 'should instantiate the Formtastic input' do
|
|
891
|
-
input =
|
|
892
|
-
Formtastic::Inputs::StringInput.
|
|
953
|
+
input = double('input', :to_html => 'some HTML')
|
|
954
|
+
expect(Formtastic::Inputs::StringInput).to receive(:new).and_return(input)
|
|
893
955
|
concat(semantic_form_for(@new_post) do |builder|
|
|
894
956
|
builder.input(:title, :as => :string)
|
|
895
957
|
end)
|
|
@@ -902,9 +964,9 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
902
964
|
class ::StringInput < Formtastic::Inputs::StringInput
|
|
903
965
|
end
|
|
904
966
|
|
|
905
|
-
input =
|
|
906
|
-
Formtastic::Inputs::StringInput.
|
|
907
|
-
::StringInput.
|
|
967
|
+
input = double('input', :to_html => 'some HTML')
|
|
968
|
+
expect(Formtastic::Inputs::StringInput).not_to receive(:new)
|
|
969
|
+
expect(::StringInput).to receive(:new).and_return(input)
|
|
908
970
|
|
|
909
971
|
concat(semantic_form_for(@new_post) do |builder|
|
|
910
972
|
builder.input(:title, :as => :string)
|
|
@@ -912,20 +974,6 @@ describe 'Formtastic::FormBuilder#input' do
|
|
|
912
974
|
end
|
|
913
975
|
end
|
|
914
976
|
|
|
915
|
-
describe 'when instantiated multiple times with the same input type' do
|
|
916
|
-
|
|
917
|
-
it "should be cached (not calling the internal methods)" do
|
|
918
|
-
# TODO this is really tied to the underlying implementation
|
|
919
|
-
concat(semantic_form_for(@new_post) do |builder|
|
|
920
|
-
builder.should_receive(:custom_input_class_name).with(:string).once.and_return(::Formtastic::Inputs::StringInput)
|
|
921
|
-
builder.input(:title, :as => :string)
|
|
922
|
-
builder.input(:title, :as => :string)
|
|
923
|
-
end)
|
|
924
|
-
end
|
|
925
|
-
|
|
926
|
-
end
|
|
927
977
|
|
|
928
978
|
end
|
|
929
|
-
|
|
930
979
|
end
|
|
931
|
-
|