formtastic 3.1.5 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +5 -5
  2. data/.gitattributes +1 -0
  3. data/.gitignore +3 -2
  4. data/.travis.yml +28 -40
  5. data/CHANGELOG.md +49 -0
  6. data/DEPRECATIONS +1 -1
  7. data/Gemfile.lock +104 -0
  8. data/README.md +628 -629
  9. data/Rakefile +20 -1
  10. data/app/assets/stylesheets/formtastic.css +1 -1
  11. data/bin/appraisal +8 -0
  12. data/formtastic.gemspec +8 -14
  13. data/gemfiles/rails_5.2/Gemfile +5 -0
  14. data/gemfiles/rails_6.0/Gemfile +5 -0
  15. data/gemfiles/rails_edge/Gemfile +13 -0
  16. data/lib/formtastic.rb +5 -11
  17. data/lib/formtastic/actions.rb +6 -3
  18. data/lib/formtastic/deprecation.rb +1 -38
  19. data/lib/formtastic/engine.rb +3 -1
  20. data/lib/formtastic/form_builder.rb +8 -24
  21. data/lib/formtastic/helpers/action_helper.rb +1 -48
  22. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  23. data/lib/formtastic/helpers/fieldset_wrapper.rb +7 -3
  24. data/lib/formtastic/helpers/input_helper.rb +18 -76
  25. data/lib/formtastic/helpers/inputs_helper.rb +12 -3
  26. data/lib/formtastic/i18n.rb +1 -1
  27. data/lib/formtastic/inputs.rb +32 -29
  28. data/lib/formtastic/inputs/base/collections.rb +1 -5
  29. data/lib/formtastic/inputs/base/errors.rb +4 -4
  30. data/lib/formtastic/inputs/base/hints.rb +1 -1
  31. data/lib/formtastic/inputs/base/timeish.rb +5 -1
  32. data/lib/formtastic/inputs/base/validations.rb +19 -9
  33. data/lib/formtastic/inputs/check_boxes_input.rb +3 -3
  34. data/lib/formtastic/inputs/color_input.rb +0 -1
  35. data/lib/formtastic/inputs/select_input.rb +1 -1
  36. data/lib/formtastic/localizer.rb +5 -7
  37. data/lib/formtastic/version.rb +1 -1
  38. data/lib/generators/templates/formtastic.rb +4 -6
  39. data/script/integration-template.rb +71 -0
  40. data/script/integration.sh +19 -0
  41. data/spec/action_class_finder_spec.rb +1 -1
  42. data/spec/actions/button_action_spec.rb +8 -8
  43. data/spec/actions/generic_action_spec.rb +60 -60
  44. data/spec/actions/input_action_spec.rb +7 -7
  45. data/spec/actions/link_action_spec.rb +10 -10
  46. data/spec/builder/custom_builder_spec.rb +36 -20
  47. data/spec/builder/error_proc_spec.rb +4 -4
  48. data/spec/builder/semantic_fields_for_spec.rb +27 -27
  49. data/spec/generators/formtastic/form/form_generator_spec.rb +25 -25
  50. data/spec/generators/formtastic/input/input_generator_spec.rb +31 -31
  51. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  52. data/spec/helpers/action_helper_spec.rb +328 -10
  53. data/spec/helpers/actions_helper_spec.rb +17 -17
  54. data/spec/helpers/form_helper_spec.rb +33 -33
  55. data/spec/helpers/input_helper_spec.rb +975 -2
  56. data/spec/helpers/inputs_helper_spec.rb +120 -105
  57. data/spec/helpers/reflection_helper_spec.rb +3 -3
  58. data/spec/helpers/semantic_errors_helper_spec.rb +22 -22
  59. data/spec/i18n_spec.rb +26 -26
  60. data/spec/input_class_finder_spec.rb +1 -1
  61. data/spec/inputs/base/collections_spec.rb +6 -6
  62. data/spec/inputs/base/validations_spec.rb +157 -19
  63. data/spec/inputs/boolean_input_spec.rb +55 -55
  64. data/spec/inputs/check_boxes_input_spec.rb +96 -95
  65. data/spec/inputs/color_input_spec.rb +51 -63
  66. data/spec/inputs/country_input_spec.rb +20 -20
  67. data/spec/inputs/custom_input_spec.rb +2 -6
  68. data/spec/inputs/datalist_input_spec.rb +1 -1
  69. data/spec/inputs/date_picker_input_spec.rb +42 -42
  70. data/spec/inputs/date_select_input_spec.rb +51 -37
  71. data/spec/inputs/datetime_picker_input_spec.rb +46 -46
  72. data/spec/inputs/datetime_select_input_spec.rb +53 -37
  73. data/spec/inputs/email_input_spec.rb +5 -5
  74. data/spec/inputs/file_input_spec.rb +6 -6
  75. data/spec/inputs/hidden_input_spec.rb +18 -18
  76. data/spec/inputs/include_blank_spec.rb +8 -8
  77. data/spec/inputs/label_spec.rb +20 -20
  78. data/spec/inputs/number_input_spec.rb +112 -112
  79. data/spec/inputs/password_input_spec.rb +5 -5
  80. data/spec/inputs/phone_input_spec.rb +5 -5
  81. data/spec/inputs/placeholder_spec.rb +5 -5
  82. data/spec/inputs/radio_input_spec.rb +63 -65
  83. data/spec/inputs/range_input_spec.rb +66 -66
  84. data/spec/inputs/readonly_spec.rb +4 -4
  85. data/spec/inputs/search_input_spec.rb +5 -5
  86. data/spec/inputs/select_input_spec.rb +92 -96
  87. data/spec/inputs/string_input_spec.rb +23 -23
  88. data/spec/inputs/text_input_spec.rb +16 -16
  89. data/spec/inputs/time_picker_input_spec.rb +43 -43
  90. data/spec/inputs/time_select_input_spec.rb +67 -54
  91. data/spec/inputs/time_zone_input_spec.rb +19 -19
  92. data/spec/inputs/url_input_spec.rb +5 -5
  93. data/spec/inputs/with_options_spec.rb +7 -7
  94. data/spec/localizer_spec.rb +17 -17
  95. data/spec/namespaced_class_finder_spec.rb +2 -2
  96. data/spec/schema.rb +21 -0
  97. data/spec/spec_helper.rb +163 -223
  98. data/spec/support/custom_macros.rb +72 -75
  99. data/spec/support/shared_examples.rb +0 -1301
  100. data/spec/support/test_environment.rb +23 -9
  101. metadata +33 -123
  102. data/Appraisals +0 -43
  103. data/CHANGELOG +0 -54
  104. data/gemfiles/rails_3.2.gemfile +0 -9
  105. data/gemfiles/rails_4.0.4.gemfile +0 -8
  106. data/gemfiles/rails_4.1.gemfile +0 -8
  107. data/gemfiles/rails_4.2.gemfile +0 -8
  108. data/gemfiles/rails_4.gemfile +0 -8
  109. data/gemfiles/rails_5.0.gemfile +0 -8
  110. data/gemfiles/rails_edge.gemfile +0 -15
  111. data/lib/formtastic/util.rb +0 -57
  112. data/spec/helpers/namespaced_action_helper_spec.rb +0 -43
  113. data/spec/helpers/namespaced_input_helper_spec.rb +0 -36
  114. data/spec/util_spec.rb +0 -66
@@ -10,1304 +10,3 @@ RSpec.shared_context 'form builder' do
10
10
  ::I18n.backend.reload!
11
11
  end
12
12
  end
13
-
14
- # TODO: move this back to spec/helpers/action_helper_spec.rb in Formtastic 4.0
15
- RSpec.shared_examples 'Action Helper' do
16
- include_context 'form builder'
17
-
18
- describe 'arguments and options' do
19
-
20
- it 'should require the first argument (the action method)' do
21
- lambda {
22
- concat(semantic_form_for(@new_post) do |builder|
23
- concat(builder.action()) # no args passed in at all
24
- end)
25
- }.should raise_error(ArgumentError)
26
- end
27
-
28
- describe ':as option' do
29
-
30
- describe 'when not provided' do
31
-
32
- it 'should default to a commit for commit' do
33
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
34
- concat(builder.action(:submit))
35
- end)
36
- output_buffer.should have_tag('form li.action.input_action', :count => 1)
37
- end
38
-
39
- it 'should default to a button for reset' do
40
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
41
- concat(builder.action(:reset))
42
- end)
43
- output_buffer.should have_tag('form li.action.input_action', :count => 1)
44
- end
45
-
46
- it 'should default to a link for cancel' do
47
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
48
- concat(builder.action(:cancel))
49
- end)
50
- output_buffer.should have_tag('form li.action.link_action', :count => 1)
51
- end
52
- end
53
-
54
- it 'should call the corresponding action class with .to_html' do
55
- [:input, :button, :link].each do |action_style|
56
- semantic_form_for(:project, :url => "http://test.host") do |builder|
57
- action_instance = double('Action instance')
58
- action_class = "#{action_style.to_s}_action".classify
59
- action_constant = "Formtastic::Actions::#{action_class}".constantize
60
-
61
- action_constant.should_receive(:new).and_return(action_instance)
62
- action_instance.should_receive(:to_html).and_return("some HTML")
63
-
64
- concat(builder.action(:submit, :as => action_style))
65
- end
66
- end
67
- end
68
-
69
- end
70
-
71
- #describe ':label option' do
72
- #
73
- # describe 'when provided' do
74
- # it 'should be passed down to the label tag' do
75
- # concat(semantic_form_for(@new_post) do |builder|
76
- # concat(builder.input(:title, :label => "Kustom"))
77
- # end)
78
- # output_buffer.should have_tag("form li label", /Kustom/)
79
- # end
80
- #
81
- # it 'should not generate a label if false' do
82
- # concat(semantic_form_for(@new_post) do |builder|
83
- # concat(builder.input(:title, :label => false))
84
- # end)
85
- # output_buffer.should_not have_tag("form li label")
86
- # end
87
- #
88
- # it 'should be dupped if frozen' do
89
- # concat(semantic_form_for(@new_post) do |builder|
90
- # concat(builder.input(:title, :label => "Kustom".freeze))
91
- # end)
92
- # output_buffer.should have_tag("form li label", /Kustom/)
93
- # end
94
- # end
95
- #
96
- # describe 'when not provided' do
97
- # describe 'when localized label is provided' do
98
- # describe 'and object is given' do
99
- # describe 'and label_str_method not :humanize' do
100
- # it 'should render a label with localized text and not apply the label_str_method' do
101
- # with_config :label_str_method, :reverse do
102
- # @localized_label_text = 'Localized title'
103
- # @new_post.stub(:meta_description)
104
- # ::I18n.backend.store_translations :en,
105
- # :formtastic => {
106
- # :labels => {
107
- # :meta_description => @localized_label_text
108
- # }
109
- # }
110
- #
111
- # concat(semantic_form_for(@new_post) do |builder|
112
- # concat(builder.input(:meta_description))
113
- # end)
114
- # output_buffer.should have_tag('form li label', /Localized title/)
115
- # end
116
- # end
117
- # end
118
- # end
119
- # end
120
- #
121
- # describe 'when localized label is NOT provided' do
122
- # describe 'and object is not given' do
123
- # it 'should default the humanized method name, passing it down to the label tag' do
124
- # ::I18n.backend.store_translations :en, :formtastic => {}
125
- # with_config :label_str_method, :humanize do
126
- # concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
127
- # concat(builder.input(:meta_description))
128
- # end)
129
- # output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
130
- # end
131
- # end
132
- # end
133
- #
134
- # describe 'and object is given' do
135
- # it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
136
- # @new_post.stub(:meta_description) # a two word method name
137
- # @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
138
- #
139
- # concat(semantic_form_for(@new_post) do |builder|
140
- # concat(builder.input(:meta_description))
141
- # end)
142
- # output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
143
- # end
144
- # end
145
- #
146
- # describe 'and object is given with label_str_method set to :capitalize' do
147
- # it 'should capitalize method name, passing it down to the label tag' do
148
- # with_config :label_str_method, :capitalize do
149
- # @new_post.stub(:meta_description)
150
- #
151
- # concat(semantic_form_for(@new_post) do |builder|
152
- # concat(builder.input(:meta_description))
153
- # end)
154
- # output_buffer.should have_tag("form li label", /#{'meta_description'.capitalize}/)
155
- # end
156
- # end
157
- # end
158
- # end
159
- #
160
- # describe 'when localized label is provided' do
161
- # before do
162
- # @localized_label_text = 'Localized title'
163
- # @default_localized_label_text = 'Default localized title'
164
- # ::I18n.backend.store_translations :en,
165
- # :formtastic => {
166
- # :labels => {
167
- # :title => @default_localized_label_text,
168
- # :published => @default_localized_label_text,
169
- # :post => {
170
- # :title => @localized_label_text,
171
- # :published => @default_localized_label_text
172
- # }
173
- # }
174
- # }
175
- # end
176
- #
177
- # it 'should render a label with localized label (I18n)' do
178
- # with_config :i18n_lookups_by_default, false do
179
- # concat(semantic_form_for(@new_post) do |builder|
180
- # concat(builder.input(:title, :label => true))
181
- # concat(builder.input(:published, :as => :boolean, :label => true))
182
- # end)
183
- # output_buffer.should have_tag('form li label', Regexp.new('^' + @localized_label_text))
184
- # end
185
- # end
186
- #
187
- # it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
188
- # with_config :i18n_lookups_by_default, false do
189
- # ::I18n.backend.store_translations :en,
190
- # :formtastic => {
191
- # :labels => {
192
- # :post => {
193
- # :title => nil,
194
- # :published => nil
195
- # }
196
- # }
197
- # }
198
- # concat(semantic_form_for(@new_post) do |builder|
199
- # concat(builder.input(:title, :label => true))
200
- # concat(builder.input(:published, :as => :boolean, :label => true))
201
- # end)
202
- # output_buffer.should have_tag('form li label', Regexp.new('^' + @default_localized_label_text))
203
- # end
204
- # end
205
- # end
206
- # end
207
- #
208
- #end
209
- #
210
- describe ':wrapper_html option' do
211
-
212
- describe 'when provided' do
213
- it 'should be passed down to the li tag' do
214
- concat(semantic_form_for(@new_post) do |builder|
215
- concat(builder.action(:submit, :wrapper_html => {:id => :another_id}))
216
- end)
217
- output_buffer.should have_tag("form li#another_id")
218
- end
219
-
220
- it 'should append given classes to li default classes' do
221
- concat(semantic_form_for(@new_post) do |builder|
222
- concat(builder.action(:submit, :wrapper_html => {:class => :another_class}))
223
- end)
224
- output_buffer.should have_tag("form li.action")
225
- output_buffer.should have_tag("form li.input_action")
226
- output_buffer.should have_tag("form li.another_class")
227
- end
228
-
229
- it 'should allow classes to be an array' do
230
- concat(semantic_form_for(@new_post) do |builder|
231
- concat(builder.action(:submit, :wrapper_html => {:class => [ :my_class, :another_class ]}))
232
- end)
233
- output_buffer.should have_tag("form li.action")
234
- output_buffer.should have_tag("form li.input_action")
235
- output_buffer.should have_tag("form li.my_class")
236
- output_buffer.should have_tag("form li.another_class")
237
- end
238
- end
239
-
240
- describe 'when not provided' do
241
- it 'should use default id and class' do
242
- concat(semantic_form_for(@new_post) do |builder|
243
- concat(builder.action(:submit))
244
- end)
245
- output_buffer.should have_tag("form li#post_submit_action")
246
- output_buffer.should have_tag("form li.action")
247
- output_buffer.should have_tag("form li.input_action")
248
- end
249
- end
250
-
251
- end
252
-
253
- end
254
-
255
- describe 'instantiating an action class' do
256
- context 'when a class does not exist' do
257
- it "should raise an error" do
258
- lambda {
259
- concat(semantic_form_for(@new_post) do |builder|
260
- builder.action(:submit, :as => :non_existant)
261
- end)
262
- }.should raise_error(Formtastic::UnknownActionError)
263
- end
264
- end
265
-
266
- context 'when a customized top-level class does not exist' do
267
- it 'should instantiate the Formtastic action' do
268
- action = double('action', :to_html => 'some HTML')
269
- Formtastic::Actions::ButtonAction.should_receive(:new).and_return(action)
270
- concat(semantic_form_for(@new_post) do |builder|
271
- builder.action(:commit, :as => :button)
272
- end)
273
- end
274
- end
275
-
276
- describe 'when a top-level (custom) action class exists' do
277
- it "should instantiate the top-level action instead of the Formtastic one" do
278
- class ::ButtonAction < Formtastic::Actions::ButtonAction
279
- end
280
-
281
- action = double('action', :to_html => 'some HTML')
282
- Formtastic::Actions::ButtonAction.should_not_receive(:new)
283
- ::ButtonAction.should_receive(:new).and_return(action)
284
-
285
- concat(semantic_form_for(@new_post) do |builder|
286
- builder.action(:commit, :as => :button)
287
- end)
288
- end
289
- end
290
-
291
- describe 'support for :as on each action' do
292
-
293
- it "should raise an error when the action does not support the :as" do
294
- lambda {
295
- concat(semantic_form_for(@new_post) do |builder|
296
- concat(builder.action(:submit, :as => :link))
297
- end)
298
- }.should raise_error(Formtastic::UnsupportedMethodForAction)
299
-
300
- lambda {
301
- concat(semantic_form_for(@new_post) do |builder|
302
- concat(builder.action(:cancel, :as => :input))
303
- end)
304
- }.should raise_error(Formtastic::UnsupportedMethodForAction)
305
-
306
- lambda {
307
- concat(semantic_form_for(@new_post) do |builder|
308
- concat(builder.action(:cancel, :as => :button))
309
- end)
310
- }.should raise_error(Formtastic::UnsupportedMethodForAction)
311
- end
312
-
313
- it "should not raise an error when the action does not support the :as" do
314
- lambda {
315
- concat(semantic_form_for(@new_post) do |builder|
316
- concat(builder.action(:cancel, :as => :link))
317
- end)
318
- }.should_not raise_error
319
-
320
- lambda {
321
- concat(semantic_form_for(@new_post) do |builder|
322
- concat(builder.action(:submit, :as => :input))
323
- end)
324
- }.should_not raise_error
325
-
326
- lambda {
327
- concat(semantic_form_for(@new_post) do |builder|
328
- concat(builder.action(:submit, :as => :button))
329
- end)
330
- }.should_not raise_error
331
-
332
- lambda {
333
- concat(semantic_form_for(@new_post) do |builder|
334
- concat(builder.action(:reset, :as => :input))
335
- end)
336
- }.should_not raise_error
337
-
338
- lambda {
339
- concat(semantic_form_for(@new_post) do |builder|
340
- concat(builder.action(:reset, :as => :button))
341
- end)
342
- }.should_not raise_error
343
- end
344
-
345
- end
346
-
347
- end
348
-
349
- end
350
-
351
- # TODO: move this back to spec/helpers/input_helper_spec.rb in Formtastic 4.0
352
- RSpec.shared_examples 'Input Helper' do
353
- include_context 'form builder'
354
-
355
- before do
356
- @errors = double('errors')
357
- @errors.stub(:[]).and_return([])
358
- @new_post.stub(:errors).and_return(@errors)
359
- end
360
-
361
- describe 'arguments and options' do
362
-
363
- it 'should require the first argument (the method on form\'s object)' do
364
- lambda {
365
- concat(semantic_form_for(@new_post) do |builder|
366
- concat(builder.input()) # no args passed in at all
367
- end)
368
- }.should raise_error(ArgumentError)
369
- end
370
-
371
- describe ':required option' do
372
-
373
- describe 'when true' do
374
-
375
- it 'should set a "required" class' do
376
- with_config :required_string, " required yo!" do
377
- concat(semantic_form_for(@new_post) do |builder|
378
- concat(builder.input(:title, :required => true))
379
- end)
380
- output_buffer.should_not have_tag('form li.optional')
381
- output_buffer.should have_tag('form li.required')
382
- end
383
- end
384
-
385
- it 'should append the "required" string to the label' do
386
- with_config :required_string, " required yo!" do
387
- concat(semantic_form_for(@new_post) do |builder|
388
- concat(builder.input(:title, :required => true))
389
- end)
390
- output_buffer.should have_tag('form li.required label', /required yo/)
391
- end
392
- end
393
- end
394
-
395
- describe 'when false' do
396
-
397
- before do
398
- @string = Formtastic::FormBuilder.optional_string = " optional yo!" # ensure there's something in the string
399
- @new_post.class.should_not_receive(:reflect_on_all_validations)
400
- end
401
-
402
- after do
403
- Formtastic::FormBuilder.optional_string = ''
404
- end
405
-
406
- it 'should set an "optional" class' do
407
- concat(semantic_form_for(@new_post) do |builder|
408
- concat(builder.input(:title, :required => false))
409
- end)
410
- output_buffer.should_not have_tag('form li.required')
411
- output_buffer.should have_tag('form li.optional')
412
- end
413
-
414
- it 'should set and "optional" class also when there is presence validator' do
415
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
416
- active_model_presence_validator([:title])
417
- ])
418
- concat(semantic_form_for(@new_post) do |builder|
419
- concat(builder.input(:title, :required => false))
420
- end)
421
- output_buffer.should_not have_tag('form li.required')
422
- output_buffer.should have_tag('form li.optional')
423
- end
424
-
425
- it 'should append the "optional" string to the label' do
426
- concat(semantic_form_for(@new_post) do |builder|
427
- concat(builder.input(:title, :required => false))
428
- end)
429
- output_buffer.should have_tag('form li.optional label', /#{@string}$/)
430
- end
431
-
432
- end
433
-
434
- describe 'when not provided' do
435
-
436
- describe 'and an object was not given' do
437
-
438
- it 'should use the default value' do
439
- Formtastic::FormBuilder.all_fields_required_by_default.should == true
440
- Formtastic::FormBuilder.all_fields_required_by_default = false
441
-
442
- concat(semantic_form_for(:project, :url => 'http://test.host/') do |builder|
443
- concat(builder.input(:title))
444
- end)
445
- output_buffer.should_not have_tag('form li.required')
446
- output_buffer.should have_tag('form li.optional')
447
-
448
- Formtastic::FormBuilder.all_fields_required_by_default = true
449
- end
450
-
451
- end
452
-
453
- describe 'and an object with :validators_on was given (ActiveModel, Active Resource)' do
454
- before do
455
- @new_post.stub(:class).and_return(::PostModel)
456
- end
457
-
458
- after do
459
- @new_post.stub(:class).and_return(::Post)
460
- end
461
- describe 'and validates_presence_of was called for the method' do
462
- it 'should be required' do
463
-
464
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
465
- active_model_presence_validator([:title])
466
- ])
467
-
468
- @new_post.class.should_receive(:validators_on).with(:body).at_least(:once).and_return([
469
- active_model_presence_validator([:body], {:if => true})
470
- ])
471
-
472
- concat(semantic_form_for(@new_post) do |builder|
473
- concat(builder.input(:title))
474
- concat(builder.input(:body))
475
- end)
476
- output_buffer.should have_tag('form li.required')
477
- output_buffer.should_not have_tag('form li.optional')
478
- end
479
-
480
- it 'should be required when there is :on => :create option on create' do
481
- with_config :required_string, " required yo!" do
482
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
483
- active_model_presence_validator([:title], {:on => :create})
484
- ])
485
- concat(semantic_form_for(@new_post) do |builder|
486
- concat(builder.input(:title))
487
- end)
488
- output_buffer.should have_tag('form li.required')
489
- output_buffer.should_not have_tag('form li.optional')
490
- end
491
- end
492
-
493
- it 'should be required when there is :create option in validation contexts array on create' do
494
- with_config :required_string, " required yo!" do
495
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
496
- active_model_presence_validator([:title], {:on => [:create]})
497
- ])
498
- concat(semantic_form_for(@new_post) do |builder|
499
- concat(builder.input(:title))
500
- end)
501
- output_buffer.should have_tag('form li.required')
502
- output_buffer.should_not have_tag('form li.optional')
503
- end
504
- end
505
-
506
- it 'should be required when there is :on => :save option on create' do
507
- with_config :required_string, " required yo!" do
508
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
509
- active_model_presence_validator([:title], {:on => :save})
510
- ])
511
- concat(semantic_form_for(@new_post) do |builder|
512
- concat(builder.input(:title))
513
- end)
514
- output_buffer.should have_tag('form li.required')
515
- output_buffer.should_not have_tag('form li.optional')
516
- end
517
- end
518
-
519
- it 'should be required when there is :save option in validation contexts array on create' do
520
- with_config :required_string, " required yo!" do
521
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
522
- active_model_presence_validator([:title], {:on => [:save]})
523
- ])
524
- concat(semantic_form_for(@new_post) do |builder|
525
- concat(builder.input(:title))
526
- end)
527
- output_buffer.should have_tag('form li.required')
528
- output_buffer.should_not have_tag('form li.optional')
529
- end
530
- end
531
-
532
- it 'should be required when there is :on => :save option on update' do
533
- with_config :required_string, " required yo!" do
534
- @fred.class.should_receive(:validators_on).with(:login).at_least(:once).and_return([
535
- active_model_presence_validator([:login], {:on => :save})
536
- ])
537
- concat(semantic_form_for(@fred) do |builder|
538
- concat(builder.input(:login))
539
- end)
540
- output_buffer.should have_tag('form li.required')
541
- output_buffer.should_not have_tag('form li.optional')
542
- end
543
- end
544
-
545
- it 'should be required when there is :save option in validation contexts array on update' do
546
- with_config :required_string, " required yo!" do
547
- @fred.class.should_receive(:validators_on).with(:login).at_least(:once).and_return([
548
- active_model_presence_validator([:login], {:on => [:save]})
549
- ])
550
- concat(semantic_form_for(@fred) do |builder|
551
- concat(builder.input(:login))
552
- end)
553
- output_buffer.should have_tag('form li.required')
554
- output_buffer.should_not have_tag('form li.optional')
555
- end
556
- end
557
-
558
- it 'should not be required when there is :on => :create option on update' do
559
- @fred.class.should_receive(:validators_on).with(:login).at_least(:once).and_return([
560
- active_model_presence_validator([:login], {:on => :create})
561
- ])
562
- concat(semantic_form_for(@fred) do |builder|
563
- concat(builder.input(:login))
564
- end)
565
- output_buffer.should_not have_tag('form li.required')
566
- output_buffer.should have_tag('form li.optional')
567
- end
568
-
569
- it 'should not be required when there is :create option in validation contexts array on update' do
570
- @fred.class.should_receive(:validators_on).with(:login).at_least(:once).and_return([
571
- active_model_presence_validator([:login], {:on => [:create]})
572
- ])
573
- concat(semantic_form_for(@fred) do |builder|
574
- concat(builder.input(:login))
575
- end)
576
- output_buffer.should_not have_tag('form li.required')
577
- output_buffer.should have_tag('form li.optional')
578
- end
579
-
580
- it 'should not be required when there is :on => :update option on create' do
581
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
582
- active_model_presence_validator([:title], {:on => :update})
583
- ])
584
- concat(semantic_form_for(@new_post) do |builder|
585
- concat(builder.input(:title))
586
- end)
587
- output_buffer.should_not have_tag('form li.required')
588
- output_buffer.should have_tag('form li.optional')
589
- end
590
-
591
- it 'should not be required when there is :update option in validation contexts array on create' do
592
- @new_post.class.should_receive(:validators_on).with(:title).at_least(:once).and_return([
593
- active_model_presence_validator([:title], {:on => [:update]})
594
- ])
595
- concat(semantic_form_for(@new_post) do |builder|
596
- concat(builder.input(:title))
597
- end)
598
- output_buffer.should_not have_tag('form li.required')
599
- output_buffer.should have_tag('form li.optional')
600
- end
601
-
602
- it 'should be not be required if the optional :if condition is not satisifed' do
603
- presence_should_be_required(:required => false, :tag => :body, :options => { :if => false })
604
- end
605
-
606
- it 'should not be required if the optional :if proc evaluates to false' do
607
- presence_should_be_required(:required => false, :tag => :body, :options => { :if => proc { |record| false } })
608
- end
609
-
610
- it 'should be required if the optional :if proc evaluates to true' do
611
- presence_should_be_required(:required => true, :tag => :body, :options => { :if => proc { |record| true } })
612
- end
613
-
614
- it 'should not be required if the optional :unless proc evaluates to true' do
615
- presence_should_be_required(:required => false, :tag => :body, :options => { :unless => proc { |record| true } })
616
- end
617
-
618
- it 'should be required if the optional :unless proc evaluates to false' do
619
- presence_should_be_required(:required => true, :tag => :body, :options => { :unless => proc { |record| false } })
620
- end
621
-
622
- it 'should be required if the optional :if with a method string evaluates to true' do
623
- @new_post.should_receive(:required_condition).and_return(true)
624
- presence_should_be_required(:required => true, :tag => :body, :options => { :if => :required_condition })
625
- end
626
-
627
- it 'should be required if the optional :if with a method string evaluates to false' do
628
- @new_post.should_receive(:required_condition).and_return(false)
629
- presence_should_be_required(:required => false, :tag => :body, :options => { :if => :required_condition })
630
- end
631
-
632
- it 'should be required if the optional :unless with a method string evaluates to false' do
633
- @new_post.should_receive(:required_condition).and_return(false)
634
- presence_should_be_required(:required => true, :tag => :body, :options => { :unless => :required_condition })
635
- end
636
-
637
- it 'should not be required if the optional :unless with a method string evaluates to true' do
638
- @new_post.should_receive(:required_condition).and_return(true)
639
- presence_should_be_required(:required => false, :tag => :body, :options => { :unless => :required_condition })
640
- end
641
- end
642
-
643
- describe 'and validates_inclusion_of was called for the method' do
644
- it 'should be required' do
645
- @new_post.class.should_receive(:validators_on).with(:published).at_least(:once).and_return([
646
- active_model_inclusion_validator([:published], {:in => [false, true]})
647
- ])
648
- should_be_required(:tag => :published, :required => true)
649
- end
650
-
651
- it 'should not be required if allow_blank is true' do
652
- @new_post.class.should_receive(:validators_on).with(:published).at_least(:once).and_return([
653
- active_model_inclusion_validator([:published], {:in => [false, true], :allow_blank => true})
654
- ])
655
- should_be_required(:tag => :published, :required => false)
656
- end
657
- end
658
-
659
- describe 'and validates_length_of was called for the method' do
660
- it 'should be required if minimum is set' do
661
- length_should_be_required(:tag => :title, :required => true, :options => {:minimum => 1})
662
- end
663
-
664
- it 'should be required if :within is set' do
665
- length_should_be_required(:tag => :title, :required => true, :options => {:within => 1..5})
666
- end
667
-
668
- it 'should not be required if :within allows zero length' do
669
- length_should_be_required(:tag => :title, :required => false, :options => {:within => 0..5})
670
- end
671
-
672
- it 'should not be required if only :minimum is zero' do
673
- length_should_be_required(:tag => :title, :required => false, :options => {:minimum => 0})
674
- end
675
-
676
- it 'should not be required if only :minimum is not set' do
677
- length_should_be_required(:tag => :title, :required => false, :options => {:maximum => 5})
678
- end
679
-
680
- it 'should not be required if allow_blank is true' do
681
- length_should_be_required(:tag => :published, :required => false, :options => {:allow_blank => true})
682
- end
683
- end
684
-
685
- def add_presence_validator(options)
686
- @new_post.class.stub(:validators_on).with(options[:tag]).and_return([
687
- active_model_presence_validator([options[:tag]], options[:options])
688
- ])
689
- end
690
-
691
- def add_length_validator(options)
692
- @new_post.class.should_receive(:validators_on).with(options[:tag]).at_least(:once) {[
693
- active_model_length_validator([options[:tag]], options[:options])
694
- ]}
695
- end
696
-
697
- # TODO make a matcher for this?
698
- def should_be_required(options)
699
- concat(semantic_form_for(@new_post) do |builder|
700
- concat(builder.input(options[:tag]))
701
- end)
702
-
703
- if options[:required]
704
- output_buffer.should_not have_tag('form li.optional')
705
- output_buffer.should have_tag('form li.required')
706
- else
707
- output_buffer.should have_tag('form li.optional')
708
- output_buffer.should_not have_tag('form li.required')
709
- end
710
- end
711
-
712
- def presence_should_be_required(options)
713
- add_presence_validator(options)
714
- should_be_required(options)
715
- end
716
-
717
- def length_should_be_required(options)
718
- add_length_validator(options)
719
- should_be_required(options)
720
- end
721
-
722
- # TODO JF reversed this during refactor, need to make sure
723
- describe 'and there are no requirement validations on the method' do
724
- before do
725
- @new_post.class.should_receive(:validators_on).with(:title).and_return([])
726
- end
727
-
728
- it 'should not be required' do
729
- concat(semantic_form_for(@new_post) do |builder|
730
- concat(builder.input(:title))
731
- end)
732
- output_buffer.should_not have_tag('form li.required')
733
- output_buffer.should have_tag('form li.optional')
734
- end
735
- end
736
-
737
- end
738
-
739
- describe 'and an object without :validators_on' do
740
-
741
- it 'should use the default value' do
742
- Formtastic::FormBuilder.all_fields_required_by_default.should == true
743
- Formtastic::FormBuilder.all_fields_required_by_default = false
744
-
745
- concat(semantic_form_for(@new_post) do |builder|
746
- concat(builder.input(:title))
747
- end)
748
- output_buffer.should_not have_tag('form li.required')
749
- output_buffer.should have_tag('form li.optional')
750
-
751
- Formtastic::FormBuilder.all_fields_required_by_default = true
752
- end
753
-
754
- end
755
-
756
- end
757
-
758
- end
759
-
760
- describe ':as option' do
761
-
762
- describe 'when not provided' do
763
-
764
- it 'should default to a string for forms without objects unless column is password' do
765
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
766
- concat(builder.input(:anything))
767
- end)
768
- output_buffer.should have_tag('form li.string')
769
- end
770
-
771
- it 'should default to password for forms without objects if column is password' do
772
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
773
- concat(builder.input(:password))
774
- concat(builder.input(:password_confirmation))
775
- concat(builder.input(:confirm_password))
776
- end)
777
- output_buffer.should have_tag('form li.password', :count => 3)
778
- end
779
-
780
- it 'should default to a string for methods on objects that don\'t respond to "column_for_attribute"' do
781
- @new_post.stub(:method_without_a_database_column)
782
- @new_post.stub(:column_for_attribute).and_return(nil)
783
- default_input_type(nil, :method_without_a_database_column).should == :string
784
- end
785
-
786
- it 'should default to :password for methods that don\'t have a column in the database but "password" is in the method name' do
787
- @new_post.stub(:password_method_without_a_database_column)
788
- @new_post.stub(:column_for_attribute).and_return(nil)
789
- default_input_type(nil, :password_method_without_a_database_column).should == :password
790
- end
791
-
792
- 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
793
- @new_post.stub(:password_method_without_a_database_column)
794
- @new_post.stub(:column_for_attribute).and_return(nil)
795
- default_input_type(nil, :password_method_without_a_database_column).should == :password
796
- end
797
-
798
- it 'should default to :number for "integer" column with name ending in "_id"' do
799
- @new_post.stub(:aws_instance_id)
800
- @new_post.stub(:column_for_attribute).with(:aws_instance_id).and_return(double('column', :type => :integer))
801
- default_input_type(:integer, :aws_instance_id).should == :number
802
- end
803
-
804
- it 'should default to :select for associations' do
805
- @new_post.class.stub(:reflect_on_association).with(:user_id).and_return(double('ActiveRecord::Reflection::AssociationReflection'))
806
- @new_post.class.stub(:reflect_on_association).with(:section_id).and_return(double('ActiveRecord::Reflection::AssociationReflection'))
807
- default_input_type(:integer, :user_id).should == :select
808
- default_input_type(:integer, :section_id).should == :select
809
- end
810
-
811
- it 'should default to :select for enum' do
812
- statuses = ActiveSupport::HashWithIndifferentAccess.new("active"=>0, "inactive"=>1)
813
- @new_post.class.stub(:statuses) { statuses }
814
- @new_post.stub(:defined_enums) { {"status" => statuses } }
815
-
816
- default_input_type(:integer, :status).should == :select
817
- end
818
-
819
- it 'should default to :password for :string column types with "password" in the method name' do
820
- default_input_type(:string, :password).should == :password
821
- default_input_type(:string, :hashed_password).should == :password
822
- default_input_type(:string, :password_hash).should == :password
823
- end
824
-
825
- it 'should default to :text for :text column types' do
826
- default_input_type(:text).should == :text
827
- end
828
-
829
- it 'should default to :date_select for :date column types' do
830
- default_input_type(:date).should == :date_select
831
- end
832
-
833
- it 'should default to :datetime_select for :datetime and :timestamp column types' do
834
- default_input_type(:datetime).should == :datetime_select
835
- default_input_type(:timestamp).should == :datetime_select
836
- end
837
-
838
- it 'should default to :time_select for :time column types' do
839
- default_input_type(:time).should == :time_select
840
- end
841
-
842
- it 'should default to :boolean for :boolean column types' do
843
- default_input_type(:boolean).should == :boolean
844
- end
845
-
846
- it 'should default to :string for :string column types' do
847
- default_input_type(:string).should == :string
848
- end
849
-
850
- it 'should default to :number for :integer, :float and :decimal column types' do
851
- default_input_type(:integer).should == :number
852
- default_input_type(:float).should == :number
853
- default_input_type(:decimal).should == :number
854
- end
855
-
856
- it 'should default to :country for :string columns named country' do
857
- default_input_type(:string, :country).should == :country
858
- end
859
-
860
- it 'should default to :email for :string columns matching email' do
861
- default_input_type(:string, :email).should == :email
862
- default_input_type(:string, :customer_email).should == :email
863
- default_input_type(:string, :email_work).should == :email
864
- end
865
-
866
- it 'should default to :url for :string columns named url or website' do
867
- default_input_type(:string, :url).should == :url
868
- default_input_type(:string, :website).should == :url
869
- default_input_type(:string, :my_url).should == :url
870
- default_input_type(:string, :hurl).should_not == :url
871
- end
872
-
873
- it 'should default to :phone for :string columns named phone or fax' do
874
- default_input_type(:string, :phone).should == :phone
875
- default_input_type(:string, :fax).should == :phone
876
- end
877
-
878
- it 'should default to :search for :string columns named search' do
879
- default_input_type(:string, :search).should == :search
880
- end
881
-
882
- it 'should default to :color for :string columns matching color' do
883
- default_input_type(:string, :color).should == :color
884
- default_input_type(:string, :user_color).should == :color
885
- default_input_type(:string, :color_for_image).should == :color
886
- end
887
-
888
- describe 'defaulting to file column' do
889
- Formtastic::FormBuilder.file_methods.each do |method|
890
- it "should default to :file for attributes that respond to ##{method}" do
891
- column = double('column')
892
-
893
- Formtastic::FormBuilder.file_methods.each do |test|
894
- ### TODO: Check if this is ok
895
- column.stub(method).with(test).and_return(method == test)
896
- end
897
-
898
- @new_post.should_receive(method).and_return(column)
899
-
900
- semantic_form_for(@new_post) do |builder|
901
- builder.send(:default_input_type, method).should == :file
902
- end
903
- end
904
- end
905
-
906
- end
907
- end
908
-
909
- it 'should call the corresponding input class with .to_html' do
910
- [:select, :time_zone, :radio, :date_select, :datetime_select, :time_select, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
911
- @new_post.stub(:generic_column_name)
912
- @new_post.stub(:column_for_attribute).and_return(double('column', :type => :string, :limit => 255))
913
- semantic_form_for(@new_post) do |builder|
914
- input_instance = double('Input instance')
915
- input_class = "#{input_style.to_s}_input".classify
916
- input_constant = "Formtastic::Inputs::#{input_class}".constantize
917
-
918
- input_constant.should_receive(:new).and_return(input_instance)
919
- input_instance.should_receive(:to_html).and_return("some HTML")
920
-
921
- concat(builder.input(:generic_column_name, :as => input_style))
922
- end
923
- end
924
- end
925
-
926
- end
927
-
928
- describe ':label option' do
929
-
930
- describe 'when provided' do
931
- it 'should be passed down to the label tag' do
932
- concat(semantic_form_for(@new_post) do |builder|
933
- concat(builder.input(:title, :label => "Kustom"))
934
- end)
935
- output_buffer.should have_tag("form li label", /Kustom/)
936
- end
937
-
938
- it 'should not generate a label if false' do
939
- concat(semantic_form_for(@new_post) do |builder|
940
- concat(builder.input(:title, :label => false))
941
- end)
942
- output_buffer.should_not have_tag("form li label")
943
- end
944
-
945
- it 'should be dupped if frozen' do
946
- concat(semantic_form_for(@new_post) do |builder|
947
- concat(builder.input(:title, :label => "Kustom".freeze))
948
- end)
949
- output_buffer.should have_tag("form li label", /Kustom/)
950
- end
951
- end
952
-
953
- describe 'when not provided' do
954
- describe 'when localized label is provided' do
955
- describe 'and object is given' do
956
- describe 'and label_str_method not :humanize' do
957
- it 'should render a label with localized text and not apply the label_str_method' do
958
- with_config :label_str_method, :reverse do
959
- @localized_label_text = 'Localized title'
960
- @new_post.stub(:meta_description)
961
- ::I18n.backend.store_translations :en,
962
- :formtastic => {
963
- :labels => {
964
- :meta_description => @localized_label_text
965
- }
966
- }
967
-
968
- concat(semantic_form_for(@new_post) do |builder|
969
- concat(builder.input(:meta_description))
970
- end)
971
- output_buffer.should have_tag('form li label', /Localized title/)
972
- end
973
- end
974
- end
975
- end
976
- end
977
-
978
- describe 'when localized label is NOT provided' do
979
- describe 'and object is not given' do
980
- it 'should default the humanized method name, passing it down to the label tag' do
981
- ::I18n.backend.store_translations :en, :formtastic => {}
982
- with_config :label_str_method, :humanize do
983
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
984
- concat(builder.input(:meta_description))
985
- end)
986
- output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
987
- end
988
- end
989
- end
990
-
991
- describe 'and object is given' do
992
- it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
993
- @new_post.stub(:meta_description) # a two word method name
994
- @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
995
-
996
- concat(semantic_form_for(@new_post) do |builder|
997
- concat(builder.input(:meta_description))
998
- end)
999
- output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
1000
- end
1001
- end
1002
-
1003
- describe 'and object is given with label_str_method set to :capitalize' do
1004
- it 'should capitalize method name, passing it down to the label tag' do
1005
- with_config :label_str_method, :capitalize do
1006
- @new_post.stub(:meta_description)
1007
-
1008
- concat(semantic_form_for(@new_post) do |builder|
1009
- concat(builder.input(:meta_description))
1010
- end)
1011
- output_buffer.should have_tag("form li label", /#{'meta_description'.capitalize}/)
1012
- end
1013
- end
1014
- end
1015
- end
1016
-
1017
- describe 'when localized label is provided' do
1018
- before do
1019
- @localized_label_text = 'Localized title'
1020
- @default_localized_label_text = 'Default localized title'
1021
- ::I18n.backend.store_translations :en,
1022
- :formtastic => {
1023
- :labels => {
1024
- :title => @default_localized_label_text,
1025
- :published => @default_localized_label_text,
1026
- :post => {
1027
- :title => @localized_label_text,
1028
- :published => @default_localized_label_text
1029
- }
1030
- }
1031
- }
1032
- end
1033
-
1034
- it 'should render a label with localized label (I18n)' do
1035
- with_config :i18n_lookups_by_default, false do
1036
- concat(semantic_form_for(@new_post) do |builder|
1037
- concat(builder.input(:title, :label => true))
1038
- concat(builder.input(:published, :as => :boolean, :label => true))
1039
- end)
1040
- output_buffer.should have_tag('form li label', Regexp.new('^' + @localized_label_text))
1041
- end
1042
- end
1043
-
1044
- it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
1045
- with_config :i18n_lookups_by_default, false do
1046
- ::I18n.backend.store_translations :en,
1047
- :formtastic => {
1048
- :labels => {
1049
- :post => {
1050
- :title => nil,
1051
- :published => nil
1052
- }
1053
- }
1054
- }
1055
- concat(semantic_form_for(@new_post) do |builder|
1056
- concat(builder.input(:title, :label => true))
1057
- concat(builder.input(:published, :as => :boolean, :label => true))
1058
- end)
1059
- output_buffer.should have_tag('form li label', Regexp.new('^' + @default_localized_label_text))
1060
- end
1061
- end
1062
- end
1063
- end
1064
-
1065
- end
1066
-
1067
- describe ':hint option' do
1068
-
1069
- describe 'when provided' do
1070
-
1071
- after do
1072
- Formtastic::FormBuilder.default_hint_class = "inline-hints"
1073
- end
1074
-
1075
- it 'should be passed down to the paragraph tag' do
1076
- hint_text = "this is the title of the post"
1077
- concat(semantic_form_for(@new_post) do |builder|
1078
- concat(builder.input(:title, :hint => hint_text))
1079
- end)
1080
- output_buffer.should have_tag("form li p.inline-hints", hint_text)
1081
- end
1082
-
1083
- it 'should have a custom hint class defaulted for all forms' do
1084
- hint_text = "this is the title of the post"
1085
- Formtastic::FormBuilder.default_hint_class = "custom-hint-class"
1086
- concat(semantic_form_for(@new_post) do |builder|
1087
- concat(builder.input(:title, :hint => hint_text))
1088
- end)
1089
- output_buffer.should have_tag("form li p.custom-hint-class", hint_text)
1090
- end
1091
- end
1092
-
1093
- describe 'when not provided' do
1094
- describe 'when localized hint (I18n) is provided' do
1095
- before do
1096
- @localized_hint_text = "This is the localized hint."
1097
- @default_localized_hint_text = "This is the default localized hint."
1098
- ::I18n.backend.store_translations :en,
1099
- :formtastic => {
1100
- :hints => {
1101
- :title => @default_localized_hint_text,
1102
- }
1103
- }
1104
- end
1105
-
1106
- after do
1107
- ::I18n.backend.reload!
1108
- end
1109
-
1110
- describe 'when provided value (hint value) is set to TRUE' do
1111
- it 'should render a hint paragraph containing a localized hint (I18n)' do
1112
- with_config :i18n_lookups_by_default, false do
1113
- ::I18n.backend.store_translations :en,
1114
- :formtastic => {
1115
- :hints => {
1116
- :post => {
1117
- :title => @localized_hint_text
1118
- }
1119
- }
1120
- }
1121
- concat(semantic_form_for(@new_post) do |builder|
1122
- concat(builder.input(:title, :hint => true))
1123
- end)
1124
- output_buffer.should have_tag('form li p.inline-hints', @localized_hint_text)
1125
- end
1126
- end
1127
-
1128
- it 'should render a hint paragraph containing an optional localized hint (I18n) if first is not set' do
1129
- with_config :i18n_lookups_by_default, false do
1130
- concat(semantic_form_for(@new_post) do |builder|
1131
- concat(builder.input(:title, :hint => true))
1132
- end)
1133
- output_buffer.should have_tag('form li p.inline-hints', @default_localized_hint_text)
1134
- end
1135
- end
1136
- end
1137
-
1138
- describe 'when provided value (label value) is set to FALSE' do
1139
- it 'should not render a hint paragraph' do
1140
- with_config :i18n_lookups_by_default, false do
1141
- concat(semantic_form_for(@new_post) do |builder|
1142
- concat(builder.input(:title, :hint => false))
1143
- end)
1144
- output_buffer.should_not have_tag('form li p.inline-hints', @localized_hint_text)
1145
- end
1146
- end
1147
- end
1148
- end
1149
-
1150
- describe 'when localized hint (I18n) is a model with attribute hints' do
1151
- it "should see the provided hash as a blank entry" do
1152
- with_config :i18n_lookups_by_default, false do
1153
- ::I18n.backend.store_translations :en,
1154
- :formtastic => {
1155
- :hints => {
1156
- :title => { # movie title
1157
- :summary => @localized_hint_text # summary of movie
1158
- }
1159
- }
1160
- }
1161
- semantic_form_for(@new_post) do |builder|
1162
- concat(builder.input(:title, :hint => true))
1163
- end
1164
- output_buffer.should_not have_tag('form li p.inline-hints', @localized_hint_text)
1165
- end
1166
- end
1167
- end
1168
-
1169
- describe 'when localized hint (I18n) is not provided' do
1170
- it 'should not render a hint paragraph' do
1171
- with_config :i18n_lookups_by_default, false do
1172
- concat(semantic_form_for(@new_post) do |builder|
1173
- concat(builder.input(:title))
1174
- end)
1175
- output_buffer.should_not have_tag('form li p.inline-hints')
1176
- end
1177
- end
1178
- end
1179
- end
1180
-
1181
- end
1182
-
1183
- describe ':wrapper_html option' do
1184
-
1185
- describe 'when provided' do
1186
- it 'should be passed down to the li tag' do
1187
- concat(semantic_form_for(@new_post) do |builder|
1188
- concat(builder.input(:title, :wrapper_html => {:id => :another_id}))
1189
- end)
1190
- output_buffer.should have_tag("form li#another_id")
1191
- end
1192
-
1193
- it 'should append given classes to li default classes' do
1194
- concat(semantic_form_for(@new_post) do |builder|
1195
- concat(builder.input(:title, :wrapper_html => {:class => :another_class}, :required => true))
1196
- end)
1197
- output_buffer.should have_tag("form li.string")
1198
- output_buffer.should have_tag("form li.required")
1199
- output_buffer.should have_tag("form li.another_class")
1200
- end
1201
-
1202
- it 'should allow classes to be an array' do
1203
- concat(semantic_form_for(@new_post) do |builder|
1204
- concat(builder.input(:title, :wrapper_html => {:class => [ :my_class, :another_class ]}))
1205
- end)
1206
- output_buffer.should have_tag("form li.string")
1207
- output_buffer.should have_tag("form li.my_class")
1208
- output_buffer.should have_tag("form li.another_class")
1209
- end
1210
-
1211
- describe 'when nil' do
1212
- it 'should not put an id attribute on the div tag' do
1213
- concat(semantic_form_for(@new_post) do |builder|
1214
- concat(builder.input(:title, :wrapper_html => {:id => nil}))
1215
- end)
1216
- output_buffer.should have_tag('form li:not([id])')
1217
- end
1218
- end
1219
- end
1220
-
1221
- describe 'when not provided' do
1222
- it 'should use default id and class' do
1223
- concat(semantic_form_for(@new_post) do |builder|
1224
- concat(builder.input(:title))
1225
- end)
1226
- output_buffer.should have_tag("form li#post_title_input")
1227
- output_buffer.should have_tag("form li.string")
1228
- end
1229
- end
1230
-
1231
- end
1232
-
1233
- describe ':collection option' do
1234
-
1235
- it "should be required on polymorphic associations" do
1236
- @new_post.stub(:commentable)
1237
- @new_post.class.stub(:reflections).and_return({
1238
- :commentable => double('macro_reflection', :options => { :polymorphic => true }, :macro => :belongs_to)
1239
- })
1240
- @new_post.stub(:column_for_attribute).with(:commentable).and_return(
1241
- double('column', :type => :integer)
1242
- )
1243
- @new_post.class.stub(:reflect_on_association).with(:commentable).and_return(
1244
- double('reflection', :macro => :belongs_to, :options => { :polymorphic => true })
1245
- )
1246
- expect {
1247
- concat(semantic_form_for(@new_post) do |builder|
1248
- concat(builder.inputs do
1249
- concat(builder.input :commentable)
1250
- end)
1251
- end)
1252
- }.to raise_error(Formtastic::PolymorphicInputWithoutCollectionError)
1253
- end
1254
-
1255
- end
1256
-
1257
- end
1258
-
1259
- describe 'options re-use' do
1260
-
1261
- it 'should retain :as option when re-using the same options hash' do
1262
- my_options = { :as => :string }
1263
- output = ''
1264
-
1265
- concat(semantic_form_for(@new_post) do |builder|
1266
- concat(builder.input(:title, my_options))
1267
- concat(builder.input(:publish_at, my_options))
1268
- end)
1269
- output_buffer.should have_tag 'li.string', :count => 2
1270
- end
1271
- end
1272
-
1273
- describe 'instantiating an input class' do
1274
- context 'when a class does not exist' do
1275
- it "should raise an error" do
1276
- lambda {
1277
- concat(semantic_form_for(@new_post) do |builder|
1278
- builder.input(:title, :as => :non_existant)
1279
- end)
1280
- }.should raise_error(Formtastic::UnknownInputError)
1281
- end
1282
- end
1283
-
1284
- context 'when a customized top-level class does not exist' do
1285
-
1286
- it 'should instantiate the Formtastic input' do
1287
- input = double('input', :to_html => 'some HTML')
1288
- Formtastic::Inputs::StringInput.should_receive(:new).and_return(input)
1289
- concat(semantic_form_for(@new_post) do |builder|
1290
- builder.input(:title, :as => :string)
1291
- end)
1292
- end
1293
-
1294
- end
1295
-
1296
- describe 'when a top-level input class exists' do
1297
- it "should instantiate the top-level input instead of the Formtastic one" do
1298
- class ::StringInput < Formtastic::Inputs::StringInput
1299
- end
1300
-
1301
- input = double('input', :to_html => 'some HTML')
1302
- Formtastic::Inputs::StringInput.should_not_receive(:new)
1303
- ::StringInput.should_receive(:new).and_return(input)
1304
-
1305
- concat(semantic_form_for(@new_post) do |builder|
1306
- builder.input(:title, :as => :string)
1307
- end)
1308
- end
1309
- end
1310
-
1311
-
1312
- end
1313
- end