formtastic-rails3 0.9.7

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.
Files changed (58) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.textile +558 -0
  3. data/Rakefile +103 -0
  4. data/generators/form/USAGE +16 -0
  5. data/generators/form/form_generator.rb +120 -0
  6. data/generators/form/templates/view__form.html.erb +5 -0
  7. data/generators/form/templates/view__form.html.haml +4 -0
  8. data/generators/formtastic/formtastic_generator.rb +24 -0
  9. data/generators/formtastic/templates/formtastic.css +144 -0
  10. data/generators/formtastic/templates/formtastic.rb +54 -0
  11. data/generators/formtastic/templates/formtastic_changes.css +10 -0
  12. data/generators/formtastic_stylesheets/formtastic_stylesheets_generator.rb +16 -0
  13. data/lib/formtastic.rb +1724 -0
  14. data/lib/formtastic/i18n.rb +32 -0
  15. data/lib/formtastic/layout_helper.rb +10 -0
  16. data/lib/generators/formtastic/form/form_generator.rb +85 -0
  17. data/lib/generators/formtastic/form/templates/_form.html.erb +5 -0
  18. data/lib/generators/formtastic/form/templates/_form.html.haml +4 -0
  19. data/lib/generators/formtastic/install/install_generator.rb +23 -0
  20. data/lib/generators/formtastic/install/templates/formtastic.css +144 -0
  21. data/lib/generators/formtastic/install/templates/formtastic.rb +58 -0
  22. data/lib/generators/formtastic/install/templates/formtastic_changes.css +10 -0
  23. data/lib/locale/en.yml +8 -0
  24. data/spec/buttons_spec.rb +149 -0
  25. data/spec/commit_button_spec.rb +377 -0
  26. data/spec/custom_builder_spec.rb +62 -0
  27. data/spec/custom_macros.rb +460 -0
  28. data/spec/defaults_spec.rb +20 -0
  29. data/spec/error_proc_spec.rb +27 -0
  30. data/spec/errors_spec.rb +85 -0
  31. data/spec/form_helper_spec.rb +110 -0
  32. data/spec/i18n_spec.rb +131 -0
  33. data/spec/include_blank_spec.rb +70 -0
  34. data/spec/input_spec.rb +632 -0
  35. data/spec/inputs/boolean_input_spec.rb +93 -0
  36. data/spec/inputs/check_boxes_input_spec.rb +167 -0
  37. data/spec/inputs/country_input_spec.rb +80 -0
  38. data/spec/inputs/currency_input_spec.rb +80 -0
  39. data/spec/inputs/date_input_spec.rb +143 -0
  40. data/spec/inputs/datetime_input_spec.rb +259 -0
  41. data/spec/inputs/file_input_spec.rb +33 -0
  42. data/spec/inputs/hidden_input_spec.rb +52 -0
  43. data/spec/inputs/numeric_input_spec.rb +44 -0
  44. data/spec/inputs/password_input_spec.rb +46 -0
  45. data/spec/inputs/radio_input_spec.rb +152 -0
  46. data/spec/inputs/select_input_spec.rb +470 -0
  47. data/spec/inputs/string_input_spec.rb +47 -0
  48. data/spec/inputs/text_input_spec.rb +33 -0
  49. data/spec/inputs/time_input_spec.rb +128 -0
  50. data/spec/inputs/time_zone_input_spec.rb +102 -0
  51. data/spec/inputs_spec.rb +395 -0
  52. data/spec/label_spec.rb +48 -0
  53. data/spec/layout_helper_spec.rb +42 -0
  54. data/spec/semantic_errors_spec.rb +98 -0
  55. data/spec/semantic_fields_for_spec.rb +44 -0
  56. data/spec/spec.opts +2 -0
  57. data/spec/spec_helper.rb +238 -0
  58. metadata +205 -0
@@ -0,0 +1,632 @@
1
+ # coding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe 'SemanticFormBuilder#input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ActiveSupport::SafeBuffer.new
10
+ mock_everything
11
+ end
12
+
13
+ describe 'with inline order customization' do
14
+ it 'should allow input, hints, errors as order' do
15
+ ::Formtastic::SemanticFormBuilder.inline_order = [:input, :hints, :errors]
16
+
17
+ semantic_form_for(@new_post) do |builder|
18
+ builder.should_receive(:inline_input_for).once.ordered
19
+ builder.should_receive(:inline_hints_for).once.ordered
20
+ builder.should_receive(:inline_errors_for).once.ordered
21
+ concat(builder.input(:title))
22
+ end
23
+ end
24
+
25
+ it 'should allow hints, input, errors as order' do
26
+ ::Formtastic::SemanticFormBuilder.inline_order = [:hints, :input, :errors]
27
+
28
+ semantic_form_for(@new_post) do |builder|
29
+ builder.should_receive(:inline_hints_for).once.ordered
30
+ builder.should_receive(:inline_input_for).once.ordered
31
+ builder.should_receive(:inline_errors_for).once.ordered
32
+ concat(builder.input(:title))
33
+ end
34
+ end
35
+ end
36
+
37
+ describe 'arguments and options' do
38
+
39
+ it 'should require the first argument (the method on form\'s object)' do
40
+ lambda {
41
+ semantic_form_for(@new_post) do |builder|
42
+ concat(builder.input()) # no args passed in at all
43
+ end
44
+ }.should raise_error(ArgumentError)
45
+ end
46
+
47
+ describe ':required option' do
48
+
49
+ describe 'when true' do
50
+
51
+ before do
52
+ @old_string = ::Formtastic::SemanticFormBuilder.required_string
53
+ @new_string = ::Formtastic::SemanticFormBuilder.required_string = " required yo!" # ensure there's something in the string
54
+ @new_post.class.should_not_receive(:validators_on)
55
+ end
56
+
57
+ after do
58
+ ::Formtastic::SemanticFormBuilder.required_string = @old_string
59
+ end
60
+
61
+ it 'should set a "required" class' do
62
+ semantic_form_for(@new_post) do |builder|
63
+ concat(builder.input(:title, :required => true))
64
+ end
65
+ output_buffer.should_not have_tag('form li.optional')
66
+ output_buffer.should have_tag('form li.required')
67
+ end
68
+
69
+ it 'should append the "required" string to the label' do
70
+ semantic_form_for(@new_post) do |builder|
71
+ concat(builder.input(:title, :required => true))
72
+ end
73
+ output_buffer.should have_tag('form li.required label', /#{@new_string}$/)
74
+ end
75
+
76
+ end
77
+
78
+ describe 'when false' do
79
+
80
+ before do
81
+ @string = ::Formtastic::SemanticFormBuilder.optional_string = " optional yo!" # ensure there's something in the string
82
+ @new_post.class.should_not_receive(:validators_on)
83
+ end
84
+
85
+ after do
86
+ ::Formtastic::SemanticFormBuilder.optional_string = ''
87
+ end
88
+
89
+ it 'should set an "optional" class' do
90
+ semantic_form_for(@new_post) do |builder|
91
+ concat(builder.input(:title, :required => false))
92
+ end
93
+ output_buffer.should_not have_tag('form li.required')
94
+ output_buffer.should have_tag('form li.optional')
95
+ end
96
+
97
+ it 'should append the "optional" string to the label' do
98
+ semantic_form_for(@new_post) do |builder|
99
+ concat(builder.input(:title, :required => false))
100
+ end
101
+ output_buffer.should have_tag('form li.optional label', /#{@string}$/)
102
+ end
103
+
104
+ end
105
+
106
+ describe 'when not provided' do
107
+
108
+ describe 'and an object was not given' do
109
+
110
+ it 'should use the default value' do
111
+ ::Formtastic::SemanticFormBuilder.all_fields_required_by_default.should == true
112
+ ::Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
113
+
114
+ semantic_form_for(:project, :url => 'http://test.host/') do |builder|
115
+ concat(builder.input(:title))
116
+ end
117
+ output_buffer.should_not have_tag('form li.required')
118
+ output_buffer.should have_tag('form li.optional')
119
+
120
+ ::Formtastic::SemanticFormBuilder.all_fields_required_by_default = true
121
+ end
122
+
123
+ end
124
+
125
+ describe 'and an object was given' do
126
+
127
+ describe 'and the validation reflection is available' do
128
+
129
+ before do
130
+ # @new_post.class.stub!(:method_defined?).with(:validators_on).and_return(true)
131
+ end
132
+
133
+ describe 'and validates_presence_of was called for the method' do
134
+ it 'should be required' do
135
+ @new_post.class.should_receive(:validators_on).with(:title).and_return([
136
+ mock('ActiveModel::Validations::PresenceValidator', :kind => :presence, :attributes => [:title], :options => nil)
137
+ ])
138
+ @new_post.class.should_receive(:validators_on).with(:body).and_return([
139
+ mock('ActiveModel::Validations::PresenceValidator', :kind => :presence, :attributes => [:body], :options => {:if => true})
140
+ ])
141
+
142
+ semantic_form_for(@new_post) do |builder|
143
+ concat(builder.input(:title))
144
+ concat(builder.input(:body))
145
+ end
146
+ output_buffer.should have_tag('form li.required')
147
+ output_buffer.should_not have_tag('form li.optional')
148
+ end
149
+
150
+ it 'should be not be required if the optional :if condition is not satisifed' do
151
+ should_be_required(:required => false, :options => { :if => false })
152
+ end
153
+
154
+ it 'should not be required if the optional :if proc evaluates to false' do
155
+ should_be_required(:required => false, :options => { :if => proc { |record| false } })
156
+ end
157
+
158
+ it 'should be required if the optional :if proc evaluates to true' do
159
+ should_be_required(:required => true, :options => { :if => proc { |record| true } })
160
+ end
161
+
162
+ it 'should not be required if the optional :unless proc evaluates to true' do
163
+ should_be_required(:required => false, :options => { :unless => proc { |record| true } })
164
+ end
165
+
166
+ it 'should be required if the optional :unless proc evaluates to false' do
167
+ should_be_required(:required => true, :options => { :unless => proc { |record| false } })
168
+ end
169
+
170
+ it 'should be required if the optional :if with a method string evaluates to true' do
171
+ @new_post.should_receive(:required_condition).and_return(true)
172
+ should_be_required(:required => true, :options => { :if => :required_condition })
173
+ end
174
+
175
+ it 'should be required if the optional :if with a method string evaluates to false' do
176
+ @new_post.should_receive(:required_condition).and_return(false)
177
+ should_be_required(:required => false, :options => { :if => :required_condition })
178
+ end
179
+
180
+ it 'should not be required if the optional :unless with a method string evaluates to false' do
181
+ @new_post.should_receive(:required_condition).and_return(false)
182
+ should_be_required(:required => true, :options => { :unless => :required_condition })
183
+ end
184
+
185
+ it 'should be required if the optional :unless with a method string evaluates to true' do
186
+ @new_post.should_receive(:required_condition).and_return(true)
187
+ should_be_required(:required => false, :options => { :unless => :required_condition })
188
+ end
189
+ end
190
+
191
+ # TODO make a matcher for this?
192
+ def should_be_required(options)
193
+ @new_post.class.should_receive(:validators_on).with(:body).and_return([
194
+ mock('ActiveModel::Validations::PresenceValidator', :kind => :presence, :attributes => [:body], :options => options[:options])
195
+ ])
196
+
197
+ semantic_form_for(@new_post) do |builder|
198
+ concat(builder.input(:body))
199
+ end
200
+
201
+ if options[:required]
202
+ output_buffer.should_not have_tag('form li.optional')
203
+ output_buffer.should have_tag('form li.required')
204
+ else
205
+ output_buffer.should have_tag('form li.optional')
206
+ output_buffer.should_not have_tag('form li.required')
207
+ end
208
+ end
209
+
210
+ describe 'and validates_presence_of was not called for the method' do
211
+ before do
212
+ @new_post.class.should_receive(:validators_on).with(:title).and_return([])
213
+ end
214
+
215
+ it 'should not be required' do
216
+ semantic_form_for(@new_post) do |builder|
217
+ concat(builder.input(:title))
218
+ end
219
+ output_buffer.should_not have_tag('form li.required')
220
+ output_buffer.should have_tag('form li.optional')
221
+ end
222
+ end
223
+
224
+ end
225
+
226
+ describe 'and the validation reflection plugin is not available' do
227
+
228
+ it 'should use the default value' do
229
+ ::Formtastic::SemanticFormBuilder.all_fields_required_by_default.should == true
230
+ ::Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
231
+
232
+ semantic_form_for(@new_post) do |builder|
233
+ concat(builder.input(:title))
234
+ end
235
+ output_buffer.should_not have_tag('form li.required')
236
+ output_buffer.should have_tag('form li.optional')
237
+
238
+ ::Formtastic::SemanticFormBuilder.all_fields_required_by_default = true
239
+ end
240
+
241
+ end
242
+
243
+ end
244
+
245
+ end
246
+
247
+ end
248
+
249
+ describe ':as option' do
250
+
251
+ describe 'when not provided' do
252
+
253
+ it 'should default to a string for forms without objects unless column is password' do
254
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
255
+ concat(builder.input(:anything))
256
+ end
257
+ output_buffer.should have_tag('form li.string')
258
+ end
259
+
260
+ it 'should default to password for forms without objects if column is password' do
261
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
262
+ concat(builder.input(:password))
263
+ concat(builder.input(:password_confirmation))
264
+ concat(builder.input(:confirm_password))
265
+ end
266
+ output_buffer.should have_tag('form li.password', :count => 3)
267
+ end
268
+
269
+ it 'should default to a string for methods on objects that don\'t respond to "column_for_attribute"' do
270
+ @new_post.stub!(:method_without_a_database_column)
271
+ @new_post.stub!(:column_for_attribute).and_return(nil)
272
+ default_input_type(nil, :method_without_a_database_column).should == :string
273
+ end
274
+
275
+ it 'should default to :password for methods that don\'t have a column in the database but "password" is in the method name' do
276
+ @new_post.stub!(:password_method_without_a_database_column)
277
+ @new_post.stub!(:column_for_attribute).and_return(nil)
278
+ default_input_type(nil, :password_method_without_a_database_column).should == :password
279
+ end
280
+
281
+ 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
282
+ @new_post.stub!(:password_method_without_a_database_column)
283
+ @new_post.stub!(:column_for_attribute).and_return(nil)
284
+ default_input_type(nil, :password_method_without_a_database_column).should == :password
285
+ end
286
+
287
+ it 'should default to :select for column names ending in "_id"' do
288
+ default_input_type(:integer, :user_id).should == :select
289
+ default_input_type(:integer, :section_id).should == :select
290
+ end
291
+
292
+ it 'should default to :password for :string column types with "password" in the method name' do
293
+ default_input_type(:string, :password).should == :password
294
+ default_input_type(:string, :hashed_password).should == :password
295
+ default_input_type(:string, :password_hash).should == :password
296
+ end
297
+
298
+ it 'should default to :text for :text column types' do
299
+ default_input_type(:text).should == :text
300
+ end
301
+
302
+ it 'should default to :date for :date column types' do
303
+ default_input_type(:date).should == :date
304
+ end
305
+
306
+ it 'should default to :datetime for :datetime and :timestamp column types' do
307
+ default_input_type(:datetime).should == :datetime
308
+ default_input_type(:timestamp).should == :datetime
309
+ end
310
+
311
+ it 'should default to :time for :time column types' do
312
+ default_input_type(:time).should == :time
313
+ end
314
+
315
+ it 'should default to :boolean for :boolean column types' do
316
+ default_input_type(:boolean).should == :boolean
317
+ end
318
+
319
+ it 'should default to :string for :string column types' do
320
+ default_input_type(:string).should == :string
321
+ end
322
+
323
+ it 'should default to :numeric for :integer, :float and :decimal column types' do
324
+ default_input_type(:integer).should == :numeric
325
+ default_input_type(:float).should == :numeric
326
+ default_input_type(:decimal).should == :numeric
327
+ end
328
+
329
+ it 'should default to :country for :string columns named country' do
330
+ default_input_type(:string, :country).should == :country
331
+ end
332
+
333
+ it 'should default to :currency for :string columns named currency' do
334
+ default_input_type(:string, :currency).should == :currency
335
+ end
336
+
337
+ describe 'defaulting to file column' do
338
+ ::Formtastic::SemanticFormBuilder.file_methods.each do |method|
339
+ it "should default to :file for attributes that respond to ##{method}" do
340
+ @new_post.stub!(:column_for_attribute).and_return(nil)
341
+ column = mock('column')
342
+
343
+ ::Formtastic::SemanticFormBuilder.file_methods.each do |test|
344
+ column.stub!(:respond_to?).with(test).and_return(method == test)
345
+ end
346
+
347
+ @new_post.should_receive(method).and_return(column)
348
+
349
+ semantic_form_for(@new_post) do |builder|
350
+ builder.send(:default_input_type, method).should == :file
351
+ end
352
+ end
353
+ end
354
+
355
+ end
356
+ end
357
+
358
+ it 'should call the corresponding input method' do
359
+ [:select, :time_zone, :radio, :date, :datetime, :time, :boolean, :check_boxes, :hidden].each do |input_style|
360
+ @new_post.stub!(:generic_column_name)
361
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
362
+ semantic_form_for(@new_post) do |builder|
363
+ builder.should_receive(:"#{input_style}_input").once.and_return("fake HTML output from #input")
364
+ concat(builder.input(:generic_column_name, :as => input_style))
365
+ end
366
+ end
367
+
368
+ [:string, :password, :numeric, :text, :file].each do |input_style|
369
+ @new_post.stub!(:generic_column_name)
370
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
371
+ semantic_form_for(@new_post) do |builder|
372
+ builder.should_receive(:basic_input_helper).once.and_return("fake HTML output from #input")
373
+ concat(builder.input(:generic_column_name, :as => input_style))
374
+ end
375
+ end
376
+ end
377
+
378
+ end
379
+
380
+ describe ':label option' do
381
+
382
+ describe 'when provided' do
383
+ it 'should be passed down to the label tag' do
384
+ semantic_form_for(@new_post) do |builder|
385
+ concat(builder.input(:title, :label => "Kustom"))
386
+ end
387
+ output_buffer.should have_tag("form li label", /Kustom/)
388
+ end
389
+
390
+ it 'should not generate a label if false' do
391
+ semantic_form_for(@new_post) do |builder|
392
+ concat(builder.input(:title, :label => false))
393
+ end
394
+ output_buffer.should_not have_tag("form li label")
395
+ end
396
+
397
+ it 'should be dupped if frozen' do
398
+ semantic_form_for(@new_post) do |builder|
399
+ concat(builder.input(:title, :label => "Kustom".freeze))
400
+ end
401
+ output_buffer.should have_tag("form li label", /Kustom/)
402
+ end
403
+ end
404
+
405
+ describe 'when not provided' do
406
+ describe 'when localized label is provided' do
407
+ describe 'and object is given' do
408
+ describe 'and label_str_method not default' do
409
+ it 'should render a label with localized label (I18n)' do
410
+ with_config :label_str_method, :capitalize do
411
+ @localized_label_text = 'Localized title'
412
+ @new_post.stub!(:meta_description)
413
+ @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return(@localized_label_text)
414
+
415
+ semantic_form_for(@new_post) do |builder|
416
+ concat(builder.input(:meta_description))
417
+ end
418
+
419
+ output_buffer.should have_tag('form li label', @localized_label_text)
420
+ end
421
+ end
422
+ end
423
+ end
424
+ end
425
+
426
+ describe 'when localized label is NOT provided' do
427
+ describe 'and object is not given' do
428
+ it 'should default the humanized method name, passing it down to the label tag' do
429
+ ::Formtastic::SemanticFormBuilder.label_str_method = :humanize
430
+
431
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
432
+ concat(builder.input(:meta_description))
433
+ end
434
+
435
+ output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
436
+ end
437
+ end
438
+
439
+ describe 'and object is given' do
440
+ it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
441
+ @new_post.stub!(:meta_description) # a two word method name
442
+ @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
443
+
444
+ semantic_form_for(@new_post) do |builder|
445
+ concat(builder.input(:meta_description))
446
+ end
447
+
448
+ output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
449
+ end
450
+ end
451
+
452
+ describe 'and object is given with label_str_method set to :capitalize' do
453
+ it 'should capitalize method name, passing it down to the label tag' do
454
+ with_config :label_str_method, :capitalize do
455
+ @new_post.stub!(:meta_description)
456
+
457
+ semantic_form_for(@new_post) do |builder|
458
+ concat(builder.input(:meta_description))
459
+ end
460
+
461
+ output_buffer.should have_tag("form li label", /#{'meta_description'.capitalize}/)
462
+ end
463
+ end
464
+ end
465
+ end
466
+
467
+ describe 'when localized label is provided' do
468
+ before do
469
+ @localized_label_text = 'Localized title'
470
+ @default_localized_label_text = 'Default localized title'
471
+ ::I18n.backend.store_translations :en,
472
+ :formtastic => {
473
+ :labels => {
474
+ :title => @default_localized_label_text,
475
+ :published => @default_localized_label_text,
476
+ :post => {
477
+ :title => @localized_label_text,
478
+ :published => @default_localized_label_text
479
+ }
480
+ }
481
+ }
482
+ ::Formtastic::SemanticFormBuilder.i18n_lookups_by_default = false
483
+ end
484
+
485
+ it 'should render a label with localized label (I18n)' do
486
+ semantic_form_for(@new_post) do |builder|
487
+ concat(builder.input(:title, :label => true))
488
+ concat(builder.input(:published, :as => :boolean, :label => true))
489
+ end
490
+ output_buffer.should have_tag('form li label', @localized_label_text)
491
+ end
492
+
493
+ it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
494
+ ::I18n.backend.store_translations :en,
495
+ :formtastic => {
496
+ :labels => {
497
+ :post => {
498
+ :title => nil,
499
+ :published => nil
500
+ }
501
+ }
502
+ }
503
+ semantic_form_for(@new_post) do |builder|
504
+ concat(builder.input(:title, :label => true))
505
+ concat(builder.input(:published, :as => :boolean, :label => true))
506
+ end
507
+ output_buffer.should have_tag('form li label', @default_localized_label_text)
508
+ end
509
+ end
510
+ end
511
+
512
+ end
513
+
514
+ describe ':hint option' do
515
+
516
+ describe 'when provided' do
517
+ it 'should be passed down to the paragraph tag' do
518
+ hint_text = "this is the title of the post"
519
+ semantic_form_for(@new_post) do |builder|
520
+ concat(builder.input(:title, :hint => hint_text))
521
+ end
522
+ output_buffer.should have_tag("form li p.inline-hints", hint_text)
523
+ end
524
+ end
525
+
526
+ describe 'when not provided' do
527
+ describe 'when localized hint (I18n) is provided' do
528
+ before do
529
+ @localized_hint_text = "This is the localized hint."
530
+ @default_localized_hint_text = "This is the default localized hint."
531
+ ::I18n.backend.store_translations :en,
532
+ :formtastic => {
533
+ :hints => {
534
+ :title => @default_localized_hint_text,
535
+ :post => {
536
+ :title => @localized_hint_text
537
+ }
538
+ }
539
+ }
540
+ ::Formtastic::SemanticFormBuilder.i18n_lookups_by_default = false
541
+ end
542
+
543
+ describe 'when provided value (hint value) is set to TRUE' do
544
+ it 'should render a hint paragraph containing a localized hint (I18n)' do
545
+ semantic_form_for(@new_post) do |builder|
546
+ concat(builder.input(:title, :hint => true))
547
+ end
548
+ output_buffer.should have_tag('form li p.inline-hints', @localized_hint_text)
549
+ end
550
+
551
+ it 'should render a hint paragraph containing an optional localized hint (I18n) if first is not set' do
552
+ ::I18n.backend.store_translations :en,
553
+ :formtastic => {
554
+ :hints => {
555
+ :post => {
556
+ :title => nil
557
+ }
558
+ }
559
+ }
560
+ semantic_form_for(@new_post) do |builder|
561
+ concat(builder.input(:title, :hint => true))
562
+ end
563
+ output_buffer.should have_tag('form li p.inline-hints', @default_localized_hint_text)
564
+ end
565
+ end
566
+
567
+ describe 'when provided value (label value) is set to FALSE' do
568
+ it 'should not render a hint paragraph' do
569
+ semantic_form_for(@new_post) do |builder|
570
+ concat(builder.input(:title, :hint => false))
571
+ end
572
+ output_buffer.should_not have_tag('form li p.inline-hints', @localized_hint_text)
573
+ end
574
+ end
575
+ end
576
+
577
+ describe 'when localized hint (I18n) is not provided' do
578
+ it 'should not render a hint paragraph' do
579
+ semantic_form_for(@new_post) do |builder|
580
+ concat(builder.input(:title))
581
+ end
582
+ output_buffer.should_not have_tag('form li p.inline-hints')
583
+ end
584
+ end
585
+ end
586
+
587
+ end
588
+
589
+ describe ':wrapper_html option' do
590
+
591
+ describe 'when provided' do
592
+ it 'should be passed down to the li tag' do
593
+ semantic_form_for(@new_post) do |builder|
594
+ concat(builder.input(:title, :wrapper_html => {:id => :another_id}))
595
+ end
596
+ output_buffer.should have_tag("form li#another_id")
597
+ end
598
+
599
+ it 'should append given classes to li default classes' do
600
+ semantic_form_for(@new_post) do |builder|
601
+ concat(builder.input(:title, :wrapper_html => {:class => :another_class}, :required => true))
602
+ end
603
+ output_buffer.should have_tag("form li.string")
604
+ output_buffer.should have_tag("form li.required")
605
+ output_buffer.should have_tag("form li.another_class")
606
+ end
607
+
608
+ it 'should allow classes to be an array' do
609
+ semantic_form_for(@new_post) do |builder|
610
+ concat(builder.input(:title, :wrapper_html => {:class => [ :my_class, :another_class ]}))
611
+ end
612
+ output_buffer.should have_tag("form li.string")
613
+ output_buffer.should have_tag("form li.my_class")
614
+ output_buffer.should have_tag("form li.another_class")
615
+ end
616
+ end
617
+
618
+ describe 'when not provided' do
619
+ it 'should use default id and class' do
620
+ semantic_form_for(@new_post) do |builder|
621
+ concat(builder.input(:title))
622
+ end
623
+ output_buffer.should have_tag("form li#post_title_input")
624
+ output_buffer.should have_tag("form li.string")
625
+ end
626
+ end
627
+
628
+ end
629
+ end
630
+
631
+ end
632
+