hashrocket-formtastic 0.2.3

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.
@@ -0,0 +1,10 @@
1
+ module JustinFrench #:nodoc:
2
+ module Formtastic #:nodoc:
3
+ class SemanticFormBuilder < ::Formtastic::SemanticFormBuilder #:nodoc:
4
+ def initialize(*args)
5
+ ::ActiveSupport::Deprecation.warn("JustinFrench::Formtastic::SemanticFormBuilder is deprecated. User Formtastic::SemanticFormBuilder instead", caller)
6
+ super
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ en:
2
+ formtastic:
3
+ yes: 'Yes'
4
+ no: 'No'
5
+ create: 'Create'
6
+ save: 'Save'
7
+ submit: 'Submit'
8
+ required: 'Required'
@@ -0,0 +1,3 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. lib formtastic])
2
+ require File.join(File.dirname(__FILE__), *%w[.. lib justin_french formtastic])
3
+ ActionView::Base.send :include, Formtastic::SemanticFormHelper
@@ -0,0 +1,3069 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'formtastic'
3
+
4
+ module FormtasticSpecHelper
5
+ def default_input_type(column_type, column_name = :generic_column_name)
6
+ @new_post.stub!(column_name)
7
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => column_type)) unless column_type.nil?
8
+
9
+ semantic_form_for(@new_post) do |builder|
10
+ @default_type = builder.send(:default_input_type, column_name)
11
+ end
12
+
13
+ return @default_type
14
+ end
15
+ end
16
+
17
+ describe 'Formtastic' do
18
+
19
+ include ActionView::Helpers::FormHelper
20
+ include ActionView::Helpers::FormTagHelper
21
+ include ActionView::Helpers::FormOptionsHelper
22
+ include ActionView::Helpers::UrlHelper
23
+ include ActionView::Helpers::TagHelper
24
+ include ActionView::Helpers::TextHelper
25
+ include ActionView::Helpers::ActiveRecordHelper
26
+ include ActionView::Helpers::RecordIdentificationHelper
27
+ include ActionView::Helpers::DateHelper
28
+ include ActionView::Helpers::CaptureHelper
29
+ include ActiveSupport
30
+ include ActionController::PolymorphicRoutes
31
+
32
+ include Formtastic::SemanticFormHelper
33
+
34
+ attr_accessor :output_buffer
35
+
36
+ def protect_against_forgery?; false; end
37
+
38
+ before do
39
+ Formtastic::SemanticFormBuilder.label_str_method = :humanize
40
+
41
+ @output_buffer = ''
42
+
43
+ # Resource-oriented styles like form_for(@post) will expect a path method for the object,
44
+ # so we're defining some here.
45
+ def post_path(o); "/posts/1"; end
46
+ def posts_path; "/posts"; end
47
+ def new_post_path; "/posts/new"; end
48
+
49
+ def author_path(o); "/authors/1"; end
50
+ def authors_path; "/authors"; end
51
+ def new_author_path; "/authors/new"; end
52
+
53
+ # Sometimes we need some classes
54
+ class Post;
55
+ def id; end
56
+ end
57
+ class Author; end
58
+
59
+ @fred = mock('user')
60
+ @fred.stub!(:class).and_return(Author)
61
+ @fred.stub!(:to_label).and_return('Fred Smith')
62
+ @fred.stub!(:login).and_return('fred_smith')
63
+ @fred.stub!(:id).and_return(37)
64
+ @fred.stub!(:new_record?).and_return(false)
65
+ @fred.stub!(:errors).and_return(mock('errors', :[] => nil))
66
+
67
+ @bob = mock('user')
68
+ @bob.stub!(:class).and_return(Author)
69
+ @bob.stub!(:to_label).and_return('Bob Rock')
70
+ @bob.stub!(:login).and_return('bob')
71
+ @bob.stub!(:id).and_return(42)
72
+ @bob.stub!(:posts).and_return([])
73
+ @bob.stub!(:post_ids).and_return([])
74
+ @bob.stub!(:new_record?).and_return(false)
75
+ @bob.stub!(:errors).and_return(mock('errors', :[] => nil))
76
+
77
+ Author.stub!(:find).and_return([@fred, @bob])
78
+ Author.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
79
+ Author.stub!(:human_name).and_return('Author')
80
+ Author.stub!(:reflect_on_all_validations).and_return([])
81
+ Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
82
+
83
+ # Sometimes we need a mock @post object and some Authors for belongs_to
84
+ @new_post = mock('post')
85
+ @new_post.stub!(:class).and_return(Post)
86
+ @new_post.stub!(:id).and_return(nil)
87
+ @new_post.stub!(:new_record?).and_return(true)
88
+ @new_post.stub!(:errors).and_return(mock('errors', :[] => nil))
89
+ @new_post.stub!(:author).and_return(nil)
90
+
91
+ @freds_post = mock('post')
92
+ @freds_post.stub!(:class).and_return(Post)
93
+ @freds_post.stub!(:to_label).and_return('Fred Smith')
94
+ @freds_post.stub!(:id).and_return(19)
95
+ @freds_post.stub!(:author).and_return(@fred)
96
+ @freds_post.stub!(:author_id).and_return(@fred.id)
97
+ @freds_post.stub!(:authors).and_return([@fred])
98
+ @freds_post.stub!(:author_ids).and_return([@fred.id])
99
+ @freds_post.stub!(:new_record?).and_return(false)
100
+ @freds_post.stub!(:errors).and_return(mock('errors', :[] => nil))
101
+ @fred.stub!(:posts).and_return([@freds_post])
102
+ @fred.stub!(:post_ids).and_return([@freds_post.id])
103
+
104
+ Post.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
105
+ Post.stub!(:human_name).and_return('Post')
106
+ Post.stub!(:reflect_on_all_validations).and_return([])
107
+ Post.stub!(:reflect_on_association).and_return do |column_name|
108
+ case column_name
109
+ when :author, :author_status
110
+ mock('reflection', :options => {}, :klass => Author, :macro => :belongs_to)
111
+ when :authors
112
+ mock('reflection', :options => {}, :klass => Author, :macro => :has_and_belongs_to_many)
113
+ end
114
+ end
115
+ Post.stub!(:find).and_return([@freds_post])
116
+ end
117
+
118
+ describe 'JustinFrench::Formtastic::SemanticFormBuilder' do
119
+ require 'justin_french/formtastic'
120
+ it 'should be deprecated' do
121
+ ::ActiveSupport::Deprecation.should_receive(:warn).with(/JustinFrench\:\:Formtastic\:\:SemanticFormBuilder/, anything())
122
+ form_for(@new_post, :builder => JustinFrench::Formtastic::SemanticFormBuilder) do |builder|
123
+ end
124
+ end
125
+ end
126
+
127
+ describe 'SemanticFormHelper' do
128
+
129
+ describe '#semantic_form_for' do
130
+
131
+ it 'yields an instance of SemanticFormBuilder' do
132
+ semantic_form_for(:post, Post.new, :url => '/hello') do |builder|
133
+ builder.class.should == Formtastic::SemanticFormBuilder
134
+ end
135
+ end
136
+
137
+ it 'adds a class of "formtastic" to the generated form' do
138
+ semantic_form_for(:post, Post.new, :url => '/hello') do |builder|
139
+ end
140
+ output_buffer.should have_tag("form.formtastic")
141
+ end
142
+
143
+ it 'adds class matching the object name to the generated form when a symbol is provided' do
144
+ semantic_form_for(:post, Post.new, :url => '/hello') do |builder|
145
+ end
146
+ output_buffer.should have_tag("form.post")
147
+
148
+ semantic_form_for(:project, :url => '/hello') do |builder|
149
+ end
150
+ output_buffer.should have_tag("form.project")
151
+ end
152
+
153
+ it 'adds class matching the object\'s class to the generated form when an object is provided' do
154
+ semantic_form_for(@new_post) do |builder|
155
+ end
156
+ output_buffer.should have_tag("form.post")
157
+ end
158
+
159
+ describe 'allows :html options' do
160
+ before(:each) do
161
+ semantic_form_for(:post, Post.new, :url => '/hello', :html => { :id => "something-special", :class => "something-extra", :multipart => true }) do |builder|
162
+ end
163
+ end
164
+
165
+ it 'to add a id of "something-special" to generated form' do
166
+ output_buffer.should have_tag("form#something-special")
167
+ end
168
+
169
+ it 'to add a class of "something-extra" to generated form' do
170
+ output_buffer.should have_tag("form.something-extra")
171
+ end
172
+
173
+ it 'to add enctype="multipart/form-data"' do
174
+ output_buffer.should have_tag('form[@enctype="multipart/form-data"]')
175
+ end
176
+ end
177
+
178
+ it 'can be called with a resource-oriented style' do
179
+ semantic_form_for(@new_post) do |builder|
180
+ builder.object.class.should == Post
181
+ builder.object_name.should == "post"
182
+ end
183
+ end
184
+
185
+ it 'can be called with a generic style and instance variable' do
186
+ semantic_form_for(:post, @new_post, :url => new_post_path) do |builder|
187
+ builder.object.class.should == Post
188
+ builder.object_name.to_s.should == "post" # TODO: is this forced .to_s a bad assumption somewhere?
189
+ end
190
+ end
191
+
192
+ it 'can be called with a generic style and inline object' do
193
+ semantic_form_for(:post, Post.new, :url => new_post_path) do |builder|
194
+ builder.object.class.should == Post
195
+ builder.object_name.to_s.should == "post" # TODO: is this forced .to_s a bad assumption somewhere?
196
+ end
197
+ end
198
+
199
+ end
200
+
201
+ describe '#semantic_fields_for' do
202
+ it 'yields an instance of SemanticFormBuilder' do
203
+ semantic_fields_for(:post, Post.new, :url => '/hello') do |builder|
204
+ builder.class.should == Formtastic::SemanticFormBuilder
205
+ end
206
+ end
207
+ end
208
+
209
+ describe '#semantic_form_remote_for' do
210
+ it 'yields an instance of SemanticFormBuilder' do
211
+ semantic_form_remote_for(:post, Post.new, :url => '/hello') do |builder|
212
+ builder.class.should == Formtastic::SemanticFormBuilder
213
+ end
214
+ end
215
+ end
216
+
217
+ describe '#semantic_form_for_remote' do
218
+ it 'yields an instance of SemanticFormBuilder' do
219
+ semantic_form_remote_for(:post, Post.new, :url => '/hello') do |builder|
220
+ builder.class.should == Formtastic::SemanticFormBuilder
221
+ end
222
+ end
223
+ end
224
+
225
+ end
226
+
227
+ describe 'SemanticFormBuilder' do
228
+
229
+ include FormtasticSpecHelper
230
+
231
+ describe "@@builder" do
232
+ before do
233
+ @new_post.stub!(:title)
234
+ @new_post.stub!(:body)
235
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
236
+ end
237
+
238
+ after do
239
+ Formtastic::SemanticFormHelper.builder = Formtastic::SemanticFormBuilder
240
+ end
241
+
242
+ it "can be overridden" do
243
+
244
+ class CustomFormBuilder < Formtastic::SemanticFormBuilder
245
+ def custom(arg1, arg2, options = {})
246
+ [arg1, arg2, options]
247
+ end
248
+ end
249
+
250
+ Formtastic::SemanticFormHelper.builder = CustomFormBuilder
251
+
252
+ semantic_form_for(@new_post) do |builder|
253
+ builder.class.should == CustomFormBuilder
254
+ builder.custom("one", "two").should == ["one", "two", {}]
255
+ end
256
+ end
257
+
258
+ end
259
+
260
+ describe 'Formtastic::SemanticFormBuilder#semantic_fields_for' do
261
+ before do
262
+ @new_post.stub!(:author).and_return(Author.new)
263
+ end
264
+
265
+ it 'yields an instance of SemanticFormBuilder' do
266
+ semantic_form_for(@new_post) do |builder|
267
+ builder.semantic_fields_for(:author) do |nested_builder|
268
+ nested_builder.class.should == Formtastic::SemanticFormBuilder
269
+ end
270
+ end
271
+ end
272
+
273
+ it 'nests the object name' do
274
+ semantic_form_for(@new_post) do |builder|
275
+ builder.semantic_fields_for(@bob) do |nested_builder|
276
+ nested_builder.object_name.should == 'post[author]'
277
+ end
278
+ end
279
+ end
280
+
281
+ it 'should sanitize html id for li tag' do
282
+ @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
283
+ semantic_form_for(@new_post) do |builder|
284
+ builder.semantic_fields_for(@bob, :index => 1) do |nested_builder|
285
+ concat(nested_builder.inputs(:login))
286
+ end
287
+ end
288
+ output_buffer.should have_tag('form fieldset.inputs #post_author_1_login_input')
289
+ output_buffer.should_not have_tag('form fieldset.inputs #post[author]_1_login_input')
290
+ end
291
+ end
292
+
293
+ describe '#label' do
294
+ it 'should humanize the given attribute' do
295
+ semantic_form_for(@new_post) do |builder|
296
+ builder.label(:login).should have_tag('label', :with => /Login/)
297
+ end
298
+ end
299
+
300
+ it 'should be printed as span' do
301
+ semantic_form_for(@new_post) do |builder|
302
+ builder.label(:login, nil, { :required => true, :as_span => true }).should have_tag('span.label abbr')
303
+ end
304
+ end
305
+
306
+ describe 'when required is given' do
307
+ it 'should append a required note' do
308
+ semantic_form_for(@new_post) do |builder|
309
+ builder.label(:login, nil, :required => true).should have_tag('label abbr')
310
+ end
311
+ end
312
+
313
+ it 'should allow require option to be given as second argument' do
314
+ semantic_form_for(@new_post) do |builder|
315
+ builder.label(:login, :required => true).should have_tag('label abbr')
316
+ end
317
+ end
318
+ end
319
+
320
+ describe 'when label is given' do
321
+ it 'should allow the text to be given as label option' do
322
+ semantic_form_for(@new_post) do |builder|
323
+ builder.label(:login, :required => true, :label => 'My label').should have_tag('label', :with => /My label/)
324
+ end
325
+ end
326
+
327
+ it 'should return nil if label is false' do
328
+ semantic_form_for(@new_post) do |builder|
329
+ builder.label(:login, :label => false).should be_blank
330
+ end
331
+ end
332
+ end
333
+ end
334
+
335
+ describe '#errors_on' do
336
+ before(:each) do
337
+ @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
338
+ @errors = mock('errors')
339
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
340
+ @errors.stub!(:[]).with(:body).and_return(nil)
341
+ @new_post.stub!(:errors).and_return(@errors)
342
+ end
343
+
344
+ describe 'and the errors will be displayed as a sentence' do
345
+ it 'should render a paragraph with the errors joined into a sentence' do
346
+ Formtastic::SemanticFormBuilder.inline_errors = :sentence
347
+ semantic_form_for(@new_post) do |builder|
348
+ builder.errors_on(:title).should have_tag('p.inline-errors', @title_errors.to_sentence)
349
+ end
350
+ end
351
+ end
352
+
353
+ describe 'and the errors will be displayed as a list' do
354
+ it 'should render an unordered list with the class errors' do
355
+ Formtastic::SemanticFormBuilder.inline_errors = :list
356
+ semantic_form_for(@new_post) do |builder|
357
+ builder.errors_on(:title).should have_tag('ul.errors')
358
+ end
359
+ end
360
+
361
+ it 'should include a list element for each of the errors within the unordered list' do
362
+ Formtastic::SemanticFormBuilder.inline_errors = :list
363
+ semantic_form_for(@new_post) do |builder|
364
+ @title_errors.each do |error|
365
+ builder.errors_on(:title).should have_tag('ul.errors li', error)
366
+ end
367
+ end
368
+ end
369
+ end
370
+
371
+ describe 'but the errors will not be shown' do
372
+ it 'should return nil' do
373
+ Formtastic::SemanticFormBuilder.inline_errors = :none
374
+ semantic_form_for(@new_post) do |builder|
375
+ builder.errors_on(:title).should be_nil
376
+ end
377
+ end
378
+ end
379
+
380
+ describe 'and no error is found on the method' do
381
+ it 'should return nil' do
382
+ Formtastic::SemanticFormBuilder.inline_errors = :sentence
383
+ semantic_form_for(@new_post) do |builder|
384
+ builder.errors_on(:body).should be_nil
385
+ end
386
+ end
387
+ end
388
+ end
389
+
390
+ describe '#input' do
391
+
392
+ before do
393
+ @new_post.stub!(:title)
394
+ @new_post.stub!(:body)
395
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
396
+ end
397
+
398
+ describe 'with inline order customization' do
399
+ it 'should allow input, hints, errors as order' do
400
+ Formtastic::SemanticFormBuilder.inline_order = [:input, :hints, :errors]
401
+
402
+ semantic_form_for(@new_post) do |builder|
403
+ builder.should_receive(:inline_input_for).once.ordered
404
+ builder.should_receive(:inline_hints_for).once.ordered
405
+ builder.should_receive(:inline_errors_for).once.ordered
406
+ concat(builder.input(:title))
407
+ end
408
+ end
409
+
410
+ it 'should allow hints, input, errors as order' do
411
+ Formtastic::SemanticFormBuilder.inline_order = [:hints, :input, :errors]
412
+
413
+ semantic_form_for(@new_post) do |builder|
414
+ builder.should_receive(:inline_hints_for).once.ordered
415
+ builder.should_receive(:inline_input_for).once.ordered
416
+ builder.should_receive(:inline_errors_for).once.ordered
417
+ concat(builder.input(:title))
418
+ end
419
+ end
420
+ end
421
+
422
+ describe 'arguments and options' do
423
+
424
+ it 'should require the first argument (the method on form\'s object)' do
425
+ lambda {
426
+ semantic_form_for(@new_post) do |builder|
427
+ concat(builder.input()) # no args passed in at all
428
+ end
429
+ }.should raise_error(ArgumentError)
430
+ end
431
+
432
+ describe ':required option' do
433
+
434
+ describe 'when true' do
435
+
436
+ before do
437
+ @string = Formtastic::SemanticFormBuilder.required_string = " required yo!" # ensure there's something in the string
438
+ @new_post.class.should_not_receive(:reflect_on_all_validations)
439
+ end
440
+
441
+ after do
442
+ Formtastic::SemanticFormBuilder.required_string = %{<abbr title="required">*</abbr>}
443
+ end
444
+
445
+ it 'should set a "required" class' do
446
+ semantic_form_for(@new_post) do |builder|
447
+ concat(builder.input(:title, :required => true))
448
+ end
449
+ output_buffer.should_not have_tag('form li.optional')
450
+ output_buffer.should have_tag('form li.required')
451
+ end
452
+
453
+ it 'should append the "required" string to the label' do
454
+ semantic_form_for(@new_post) do |builder|
455
+ concat(builder.input(:title, :required => true))
456
+ end
457
+ output_buffer.should have_tag('form li.required label', /#{@string}$/)
458
+ end
459
+
460
+ end
461
+
462
+ describe 'when false' do
463
+
464
+ before do
465
+ @string = Formtastic::SemanticFormBuilder.optional_string = " optional yo!" # ensure there's something in the string
466
+ @new_post.class.should_not_receive(:reflect_on_all_validations)
467
+ end
468
+
469
+ after do
470
+ Formtastic::SemanticFormBuilder.optional_string = ''
471
+ end
472
+
473
+ it 'should set an "optional" class' do
474
+ semantic_form_for(@new_post) do |builder|
475
+ concat(builder.input(:title, :required => false))
476
+ end
477
+ output_buffer.should_not have_tag('form li.required')
478
+ output_buffer.should have_tag('form li.optional')
479
+ end
480
+
481
+ it 'should append the "optional" string to the label' do
482
+ semantic_form_for(@new_post) do |builder|
483
+ concat(builder.input(:title, :required => false))
484
+ end
485
+ output_buffer.should have_tag('form li.optional label', /#{@string}$/)
486
+ end
487
+
488
+ end
489
+
490
+ describe 'when not provided' do
491
+
492
+ describe 'and an object was not given' do
493
+
494
+ it 'should use the default value' do
495
+ Formtastic::SemanticFormBuilder.all_fields_required_by_default.should == true
496
+ Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
497
+
498
+ semantic_form_for(:project, :url => 'http://test.host/') do |builder|
499
+ concat(builder.input(:title))
500
+ end
501
+ output_buffer.should_not have_tag('form li.required')
502
+ output_buffer.should have_tag('form li.optional')
503
+
504
+ Formtastic::SemanticFormBuilder.all_fields_required_by_default = true
505
+ end
506
+
507
+ end
508
+
509
+ describe 'and an object was given' do
510
+
511
+ describe 'and the validation reflection plugin is available' do
512
+
513
+ before do
514
+ @new_post.class.stub!(:method_defined?).with(:reflect_on_all_validations).and_return(true)
515
+ end
516
+
517
+ describe 'and validates_presence_of was called for the method' do
518
+ before do
519
+ @new_post.class.should_receive(:reflect_on_all_validations).and_return([
520
+ mock('MacroReflection', :macro => :validates_presence_of, :name => :title)
521
+ ])
522
+ end
523
+
524
+ it 'should be required' do
525
+ semantic_form_for(@new_post) do |builder|
526
+ concat(builder.input(:title))
527
+ end
528
+ output_buffer.should have_tag('form li.required')
529
+ output_buffer.should_not have_tag('form li.optional')
530
+ end
531
+ end
532
+
533
+ describe 'and validates_presence_of was not called for the method' do
534
+ before do
535
+ @new_post.class.should_receive(:reflect_on_all_validations).and_return([])
536
+ end
537
+
538
+ it 'should not be required' do
539
+ semantic_form_for(@new_post) do |builder|
540
+ concat(builder.input(:title))
541
+ end
542
+ output_buffer.should_not have_tag('form li.required')
543
+ output_buffer.should have_tag('form li.optional')
544
+ end
545
+ end
546
+
547
+ end
548
+
549
+ describe 'and the validation reflection plugin is not available' do
550
+
551
+ it 'should use the default value' do
552
+ Formtastic::SemanticFormBuilder.all_fields_required_by_default.should == true
553
+ Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
554
+
555
+ semantic_form_for(@new_post) do |builder|
556
+ concat(builder.input(:title))
557
+ end
558
+ output_buffer.should_not have_tag('form li.required')
559
+ output_buffer.should have_tag('form li.optional')
560
+
561
+ Formtastic::SemanticFormBuilder.all_fields_required_by_default = true
562
+ end
563
+
564
+ end
565
+
566
+ end
567
+
568
+ end
569
+
570
+ end
571
+
572
+ describe ':as option' do
573
+
574
+ describe 'when not provided' do
575
+
576
+ it 'should default to a string for forms without objects unless column is password' do
577
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
578
+ concat(builder.input(:anything))
579
+ end
580
+ output_buffer.should have_tag('form li.string')
581
+ end
582
+
583
+ it 'should default to password for forms without objects if column is password' do
584
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
585
+ concat(builder.input(:password))
586
+ concat(builder.input(:password_confirmation))
587
+ concat(builder.input(:confirm_password))
588
+ end
589
+ output_buffer.should have_tag('form li.password', :count => 3)
590
+ end
591
+
592
+ it 'should default to a string for methods on objects that don\'t respond to "column_for_attribute"' do
593
+ @new_post.stub!(:method_without_a_database_column)
594
+ @new_post.stub!(:column_for_attribute).and_return(nil)
595
+ default_input_type(nil, :method_without_a_database_column).should == :string
596
+ end
597
+
598
+ it 'should default to :password for methods that don\'t have a column in the database but "password" is in the method name' do
599
+ @new_post.stub!(:password_method_without_a_database_column)
600
+ @new_post.stub!(:column_for_attribute).and_return(nil)
601
+ default_input_type(nil, :password_method_without_a_database_column).should == :password
602
+ end
603
+
604
+ 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
605
+ @new_post.stub!(:password_method_without_a_database_column)
606
+ @new_post.stub!(:column_for_attribute).and_return(nil)
607
+ default_input_type(nil, :password_method_without_a_database_column).should == :password
608
+ end
609
+
610
+ it 'should default to :select for column names ending in "_id"' do
611
+ default_input_type(:integer, :user_id).should == :select
612
+ default_input_type(:integer, :section_id).should == :select
613
+ end
614
+
615
+ it 'should default to :password for :string column types with "password" in the method name' do
616
+ default_input_type(:string, :password).should == :password
617
+ default_input_type(:string, :hashed_password).should == :password
618
+ default_input_type(:string, :password_hash).should == :password
619
+ end
620
+
621
+ it 'should default to :text for :text column types' do
622
+ default_input_type(:text).should == :text
623
+ end
624
+
625
+ it 'should default to :date for :date column types' do
626
+ default_input_type(:date).should == :date
627
+ end
628
+
629
+ it 'should default to :datetime for :datetime and :timestamp column types' do
630
+ default_input_type(:datetime).should == :datetime
631
+ default_input_type(:timestamp).should == :datetime
632
+ end
633
+
634
+ it 'should default to :time for :time column types' do
635
+ default_input_type(:time).should == :time
636
+ end
637
+
638
+ it 'should default to :boolean for :boolean column types' do
639
+ default_input_type(:boolean).should == :boolean
640
+ end
641
+
642
+ it 'should default to :string for :string column types' do
643
+ default_input_type(:string).should == :string
644
+ end
645
+
646
+ it 'should default to :numeric for :integer, :float and :decimal column types' do
647
+ default_input_type(:integer).should == :numeric
648
+ default_input_type(:float).should == :numeric
649
+ default_input_type(:decimal).should == :numeric
650
+ end
651
+
652
+ it 'should default to :country for :string columns named country' do
653
+ default_input_type(:string, :country).should == :country
654
+ end
655
+
656
+ describe 'defaulting to file column' do
657
+ Formtastic::SemanticFormBuilder.file_methods.each do |method|
658
+ it "should default to :file for attributes that respond to ##{method}" do
659
+ @new_post.stub!(:column_for_attribute).and_return(nil)
660
+ column = mock('column')
661
+
662
+ Formtastic::SemanticFormBuilder.file_methods.each do |test|
663
+ column.stub!(:respond_to?).with(test).and_return(method == test)
664
+ end
665
+
666
+ @new_post.should_receive(method).and_return(column)
667
+
668
+ semantic_form_for(@new_post) do |builder|
669
+ builder.send(:default_input_type, method).should == :file
670
+ end
671
+ end
672
+ end
673
+
674
+ end
675
+ end
676
+
677
+ it 'should call the corresponding input method' do
678
+ [:select, :time_zone, :radio, :date, :datetime, :time, :boolean, :check_boxes, :hidden].each do |input_style|
679
+ @new_post.stub!(:generic_column_name)
680
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
681
+ semantic_form_for(@new_post) do |builder|
682
+ builder.should_receive(:"#{input_style}_input").once.and_return("fake HTML output from #input")
683
+ concat(builder.input(:generic_column_name, :as => input_style))
684
+ end
685
+ end
686
+
687
+ Formtastic::SemanticFormBuilder::INPUT_MAPPINGS.keys.each do |input_style|
688
+ @new_post.stub!(:generic_column_name)
689
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
690
+ semantic_form_for(@new_post) do |builder|
691
+ builder.should_receive(:input_simple).once.and_return("fake HTML output from #input")
692
+ concat(builder.input(:generic_column_name, :as => input_style))
693
+ end
694
+ end
695
+ end
696
+
697
+ end
698
+
699
+ describe ':label option' do
700
+
701
+ describe 'when provided' do
702
+ it 'should be passed down to the label tag' do
703
+ semantic_form_for(@new_post) do |builder|
704
+ concat(builder.input(:title, :label => "Kustom"))
705
+ end
706
+ output_buffer.should have_tag("form li label", /Kustom/)
707
+ end
708
+
709
+ it 'should not generate a label if false' do
710
+ semantic_form_for(@new_post) do |builder|
711
+ concat(builder.input(:title, :label => false))
712
+ end
713
+ output_buffer.should_not have_tag("form li label")
714
+ end
715
+
716
+ it 'should be dupped if frozen' do
717
+ semantic_form_for(@new_post) do |builder|
718
+ concat(builder.input(:title, :label => "Kustom".freeze))
719
+ end
720
+ output_buffer.should have_tag("form li label", /Kustom/)
721
+ end
722
+ end
723
+
724
+ describe 'when not provided' do
725
+ describe 'when localized label is NOT provided' do
726
+ describe 'and object is not given' do
727
+ it 'should default the humanized method name, passing it down to the label tag' do
728
+ Formtastic::SemanticFormBuilder.label_str_method = :humanize
729
+
730
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
731
+ concat(builder.input(:meta_description))
732
+ end
733
+
734
+ output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
735
+ end
736
+ end
737
+
738
+ describe 'and object is given' do
739
+ it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
740
+ @new_post.stub!(:meta_description) # a two word method name
741
+ @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
742
+
743
+ semantic_form_for(@new_post) do |builder|
744
+ concat(builder.input(:meta_description))
745
+ end
746
+
747
+ output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
748
+ end
749
+ end
750
+ end
751
+
752
+ describe 'when localized label is provided' do
753
+ before do
754
+ @localized_label_text = 'Localized title'
755
+ @default_localized_label_text = 'Default localized title'
756
+ ::I18n.backend.store_translations :en,
757
+ :formtastic => {
758
+ :labels => {
759
+ :title => @default_localized_label_text,
760
+ :post => {
761
+ :title => @localized_label_text
762
+ }
763
+ }
764
+ }
765
+ ::Formtastic::SemanticFormBuilder.i18n_lookups_by_default = false
766
+ end
767
+
768
+ it 'should render a label with localized label (I18n)' do
769
+ semantic_form_for(@new_post) do |builder|
770
+ concat(builder.input(:title, :label => true))
771
+ end
772
+ output_buffer.should have_tag('form li label', @localized_label_text)
773
+ end
774
+
775
+ it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
776
+ ::I18n.backend.store_translations :en,
777
+ :formtastic => {
778
+ :labels => {
779
+ :post => {
780
+ :title => nil
781
+ }
782
+ }
783
+ }
784
+ semantic_form_for(@new_post) do |builder|
785
+ concat(builder.input(:title, :label => true))
786
+ end
787
+ output_buffer.should have_tag('form li label', @default_localized_label_text)
788
+ end
789
+ end
790
+ end
791
+
792
+ end
793
+
794
+ describe ':hint option' do
795
+
796
+ describe 'when provided' do
797
+ it 'should be passed down to the paragraph tag' do
798
+ hint_text = "this is the title of the post"
799
+ semantic_form_for(@new_post) do |builder|
800
+ concat(builder.input(:title, :hint => hint_text))
801
+ end
802
+ output_buffer.should have_tag("form li p.inline-hints", hint_text)
803
+ end
804
+ end
805
+
806
+ describe 'when not provided' do
807
+ describe 'when localized hint (I18n) is provided' do
808
+ before do
809
+ @localized_hint_text = "This is the localized hint."
810
+ @default_localized_hint_text = "This is the default localized hint."
811
+ ::I18n.backend.store_translations :en,
812
+ :formtastic => {
813
+ :hints => {
814
+ :title => @default_localized_hint_text,
815
+ :post => {
816
+ :title => @localized_hint_text
817
+ }
818
+ }
819
+ }
820
+ ::Formtastic::SemanticFormBuilder.i18n_lookups_by_default = false
821
+ end
822
+
823
+ describe 'when provided value (hint value) is set to TRUE' do
824
+ it 'should render a hint paragraph containing a localized hint (I18n)' do
825
+ semantic_form_for(@new_post) do |builder|
826
+ concat(builder.input(:title, :hint => true))
827
+ end
828
+ output_buffer.should have_tag('form li p.inline-hints', @localized_hint_text)
829
+ end
830
+
831
+ it 'should render a hint paragraph containing an optional localized hint (I18n) if first is not set' do
832
+ ::I18n.backend.store_translations :en,
833
+ :formtastic => {
834
+ :hints => {
835
+ :post => {
836
+ :title => nil
837
+ }
838
+ }
839
+ }
840
+ semantic_form_for(@new_post) do |builder|
841
+ concat(builder.input(:title, :hint => true))
842
+ end
843
+ output_buffer.should have_tag('form li p.inline-hints', @default_localized_hint_text)
844
+ end
845
+ end
846
+
847
+ describe 'when provided value (label value) is set to FALSE' do
848
+ it 'should not render a hint paragraph' do
849
+ semantic_form_for(@new_post) do |builder|
850
+ concat(builder.input(:title, :hint => false))
851
+ end
852
+ output_buffer.should_not have_tag('form li p.inline-hints', @localized_hint_text)
853
+ end
854
+ end
855
+ end
856
+
857
+ describe 'when localized hint (I18n) is not provided' do
858
+ it 'should not render a hint paragraph' do
859
+ semantic_form_for(@new_post) do |builder|
860
+ concat(builder.input(:title))
861
+ end
862
+ output_buffer.should_not have_tag('form li p.inline-hints')
863
+ end
864
+ end
865
+ end
866
+
867
+ end
868
+
869
+ describe ':wrapper_html option' do
870
+
871
+ describe 'when provided' do
872
+ it 'should be passed down to the li tag' do
873
+ semantic_form_for(@new_post) do |builder|
874
+ concat(builder.input(:title, :wrapper_html => {:id => :another_id}))
875
+ end
876
+ output_buffer.should have_tag("form li#another_id")
877
+ end
878
+
879
+ it 'should append given classes to li default classes' do
880
+ semantic_form_for(@new_post) do |builder|
881
+ concat(builder.input(:title, :wrapper_html => {:class => :another_class}, :required => true))
882
+ end
883
+ output_buffer.should have_tag("form li.string")
884
+ output_buffer.should have_tag("form li.required")
885
+ output_buffer.should have_tag("form li.another_class")
886
+ end
887
+
888
+ it 'should allow classes to be an array' do
889
+ semantic_form_for(@new_post) do |builder|
890
+ concat(builder.input(:title, :wrapper_html => {:class => [ :my_class, :another_class ]}))
891
+ end
892
+ output_buffer.should have_tag("form li.string")
893
+ output_buffer.should have_tag("form li.my_class")
894
+ output_buffer.should have_tag("form li.another_class")
895
+ end
896
+ end
897
+
898
+ describe 'when not provided' do
899
+ it 'should use default id and class' do
900
+ semantic_form_for(@new_post) do |builder|
901
+ concat(builder.input(:title))
902
+ end
903
+ output_buffer.should have_tag("form li#post_title_input")
904
+ output_buffer.should have_tag("form li.string")
905
+ end
906
+ end
907
+
908
+ end
909
+ end
910
+
911
+ describe ':as any type of input' do
912
+
913
+ it 'should create a list item for each input' do
914
+ semantic_form_for(@new_post) do |builder|
915
+ concat(builder.input(:title))
916
+ concat(builder.input(:body))
917
+ end
918
+ output_buffer.should have_tag('form li', :count => 2)
919
+ end
920
+
921
+ describe 'when there are errors on the object for this method' do
922
+ before do
923
+ @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
924
+ @errors = mock('errors')
925
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
926
+ @new_post.stub!(:errors).and_return(@errors)
927
+ end
928
+
929
+ it 'should apply an errors class to the list item' do
930
+ semantic_form_for(@new_post) do |builder|
931
+ concat(builder.input(:title))
932
+ end
933
+ output_buffer.should have_tag('form li.error')
934
+ end
935
+
936
+ it 'should not wrap the input with the Rails default error wrapping' do
937
+ semantic_form_for(@new_post) do |builder|
938
+ concat(builder.input(:title))
939
+ end
940
+ output_buffer.should_not have_tag('div.fieldWithErrors')
941
+ end
942
+
943
+ it 'should render a paragraph for the errors' do
944
+ Formtastic::SemanticFormBuilder.inline_errors = :sentence
945
+ semantic_form_for(@new_post) do |builder|
946
+ concat(builder.input(:title))
947
+ end
948
+ output_buffer.should have_tag('form li.error p.inline-errors')
949
+ end
950
+
951
+ it 'should not display an error list' do
952
+ Formtastic::SemanticFormBuilder.inline_errors = :list
953
+ semantic_form_for(@new_post) do |builder|
954
+ concat(builder.input(:title))
955
+ end
956
+ output_buffer.should have_tag('form li.error ul.errors')
957
+ end
958
+ end
959
+
960
+ describe 'when there are no errors on the object for this method' do
961
+ before do
962
+ semantic_form_for(@new_post) do |builder|
963
+ concat(builder.input(:title))
964
+ end
965
+ end
966
+
967
+ it 'should not apply an errors class to the list item' do
968
+ output_buffer.should_not have_tag('form li.error')
969
+ end
970
+
971
+ it 'should not render a paragraph for the errors' do
972
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
973
+ end
974
+
975
+ it 'should not display an error list' do
976
+ output_buffer.should_not have_tag('form li.error ul.errors')
977
+ end
978
+ end
979
+
980
+ describe 'when no object is provided' do
981
+ before do
982
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
983
+ concat(builder.input(:title))
984
+ end
985
+ end
986
+
987
+ it 'should not apply an errors class to the list item' do
988
+ output_buffer.should_not have_tag('form li.error')
989
+ end
990
+
991
+ it 'should not render a paragraph for the errors' do
992
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
993
+ end
994
+
995
+ it 'should not display an error list' do
996
+ output_buffer.should_not have_tag('form li.error ul.errors')
997
+ end
998
+ end
999
+ end
1000
+
1001
+ # Test string_mappings: :string, :password and :numeric
1002
+ string_mappings = Formtastic::SemanticFormBuilder::INPUT_MAPPINGS.slice(*Formtastic::SemanticFormBuilder::STRING_MAPPINGS)
1003
+ string_mappings.each do |type, template_method|
1004
+ describe ":as => #{type.inspect}" do
1005
+
1006
+ before do
1007
+ @new_post.stub!(:title)
1008
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => type, :limit => 50))
1009
+
1010
+ semantic_form_for(@new_post) do |builder|
1011
+ concat(builder.input(:title, :as => type))
1012
+ end
1013
+ end
1014
+
1015
+ it "should have a #{type} class on the wrapper" do
1016
+ output_buffer.should have_tag("form li.#{type}")
1017
+ end
1018
+
1019
+ it 'should have a post_title_input id on the wrapper' do
1020
+ output_buffer.should have_tag('form li#post_title_input')
1021
+ end
1022
+
1023
+ it 'should generate a label for the input' do
1024
+ output_buffer.should have_tag('form li label')
1025
+ output_buffer.should have_tag('form li label[@for="post_title"')
1026
+ output_buffer.should have_tag('form li label', /Title/)
1027
+ end
1028
+
1029
+ input_type = template_method.to_s.split('_').first
1030
+
1031
+ it "should generate a #{input_type} input" do
1032
+ output_buffer.should have_tag("form li input")
1033
+ output_buffer.should have_tag("form li input#post_title")
1034
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
1035
+ output_buffer.should have_tag("form li input[@name=\"post[title]\"]")
1036
+ end
1037
+
1038
+ unless type == :numeric
1039
+ it 'should have a maxlength matching the column limit' do
1040
+ @new_post.column_for_attribute(:title).limit.should == 50
1041
+ output_buffer.should have_tag("form li input[@maxlength='50']")
1042
+ end
1043
+
1044
+ it 'should use default_text_field_size for columns longer than default_text_field_size' do
1045
+ default_size = Formtastic::SemanticFormBuilder.default_text_field_size
1046
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => type, :limit => default_size * 2))
1047
+
1048
+ semantic_form_for(@new_post) do |builder|
1049
+ concat(builder.input(:title, :as => type))
1050
+ end
1051
+
1052
+ output_buffer.should have_tag("form li input[@size='#{default_size}']")
1053
+ end
1054
+
1055
+ it 'should use the column size for columns shorter than default_text_field_size' do
1056
+ column_limit_shorted_than_default = 1
1057
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => type, :limit => column_limit_shorted_than_default))
1058
+
1059
+ semantic_form_for(@new_post) do |builder|
1060
+ concat(builder.input(:title, :as => type))
1061
+ end
1062
+
1063
+ output_buffer.should have_tag("form li input[@size='#{column_limit_shorted_than_default}']")
1064
+ end
1065
+ end
1066
+
1067
+ it 'should use default_text_field_size for methods without database columns' do
1068
+ default_size = Formtastic::SemanticFormBuilder.default_text_field_size
1069
+ @new_post.stub!(:column_for_attribute).and_return(nil) # Return a nil column
1070
+
1071
+ semantic_form_for(@new_post) do |builder|
1072
+ concat(builder.input(:title, :as => type))
1073
+ end
1074
+
1075
+ output_buffer.should have_tag("form li input[@size='#{default_size}']")
1076
+ end
1077
+
1078
+ it 'should use input_html to style inputs' do
1079
+ semantic_form_for(@new_post) do |builder|
1080
+ concat(builder.input(:title, :as => type, :input_html => { :class => 'myclass' }))
1081
+ end
1082
+ output_buffer.should have_tag("form li input.myclass")
1083
+ end
1084
+
1085
+ it 'should consider input_html :id in labels' do
1086
+ semantic_form_for(@new_post) do |builder|
1087
+ concat(builder.input(:title, :as => type, :input_html => { :id => 'myid' }))
1088
+ end
1089
+ output_buffer.should have_tag('form li label[@for="myid"]')
1090
+ end
1091
+
1092
+ it 'should generate input and labels even if no object is given' do
1093
+ semantic_form_for(:project, :url => 'http://test.host/') do |builder|
1094
+ concat(builder.input(:title, :as => type))
1095
+ end
1096
+
1097
+ output_buffer.should have_tag('form li label')
1098
+ output_buffer.should have_tag('form li label[@for="project_title"')
1099
+ output_buffer.should have_tag('form li label', /Title/)
1100
+
1101
+ output_buffer.should have_tag("form li input")
1102
+ output_buffer.should have_tag("form li input#project_title")
1103
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
1104
+ output_buffer.should have_tag("form li input[@name=\"project[title]\"]")
1105
+ end
1106
+
1107
+ end
1108
+ end
1109
+
1110
+ # Test other mappings that are not strings: :text and :file.
1111
+ other_mappings = Formtastic::SemanticFormBuilder::INPUT_MAPPINGS.except(*Formtastic::SemanticFormBuilder::STRING_MAPPINGS)
1112
+ other_mappings.each do |type, template_method|
1113
+ describe ":as => #{type.inspect}" do
1114
+
1115
+ before do
1116
+ @new_post.stub!(:body)
1117
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => type))
1118
+
1119
+ semantic_form_for(@new_post) do |builder|
1120
+ concat(builder.input(:body, :as => type))
1121
+ end
1122
+ end
1123
+
1124
+ it "should have a #{type} class on the wrapper" do
1125
+ output_buffer.should have_tag('form li.#{type}')
1126
+ end
1127
+
1128
+ it 'should have a post_title_input id on the wrapper' do
1129
+ output_buffer.should have_tag('form li#post_body_input')
1130
+ end
1131
+
1132
+ it 'should generate a label for the input' do
1133
+ output_buffer.should have_tag('form li label')
1134
+ output_buffer.should have_tag('form li label[@for="post_body"')
1135
+ output_buffer.should have_tag('form li label', /Body/)
1136
+ end
1137
+
1138
+ input_type = template_method.to_s.gsub(/_field|_/, '')
1139
+
1140
+ if template_method.to_s =~ /_field$/ # password_field
1141
+
1142
+ it "should generate a #{input_type} input" do
1143
+ output_buffer.should have_tag("form li input")
1144
+ output_buffer.should have_tag("form li input#post_body")
1145
+ output_buffer.should have_tag("form li input[@name=\"post[body]\"]")
1146
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
1147
+ end
1148
+
1149
+ it 'should use input_html to style inputs' do
1150
+ semantic_form_for(@new_post) do |builder|
1151
+ concat(builder.input(:title, :as => type, :input_html => { :class => 'myclass' }))
1152
+ end
1153
+ output_buffer.should have_tag("form li input.myclass")
1154
+ end
1155
+
1156
+ else # text_area
1157
+
1158
+ it "should generate a #{input_type} input" do
1159
+ output_buffer.should have_tag("form li #{input_type}")
1160
+ output_buffer.should have_tag("form li #{input_type}#post_body")
1161
+ output_buffer.should have_tag("form li #{input_type}[@name=\"post[body]\"]")
1162
+ end
1163
+
1164
+ it 'should use input_html to style inputs' do
1165
+ semantic_form_for(@new_post) do |builder|
1166
+ concat(builder.input(:title, :as => type, :input_html => { :class => 'myclass' }))
1167
+ end
1168
+ output_buffer.should have_tag("form li #{input_type}.myclass")
1169
+ end
1170
+
1171
+ end
1172
+
1173
+ describe 'when no object is given' do
1174
+ before(:each) do
1175
+ semantic_form_for(:project, :url => 'http://test.host/') do |builder|
1176
+ concat(builder.input(:title, :as => type))
1177
+ end
1178
+ end
1179
+
1180
+ it 'should generate input' do
1181
+ if template_method.to_s =~ /_field$/ # password_field
1182
+ output_buffer.should have_tag("form li input")
1183
+ output_buffer.should have_tag("form li input#project_title")
1184
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
1185
+ output_buffer.should have_tag("form li input[@name=\"project[title]\"]")
1186
+ else
1187
+ output_buffer.should have_tag("form li #{input_type}")
1188
+ output_buffer.should have_tag("form li #{input_type}#project_title")
1189
+ output_buffer.should have_tag("form li #{input_type}[@name=\"project[title]\"]")
1190
+ end
1191
+ end
1192
+
1193
+ it 'should generate labels' do
1194
+ output_buffer.should have_tag('form li label')
1195
+ output_buffer.should have_tag('form li label[@for="project_title"')
1196
+ output_buffer.should have_tag('form li label', /Title/)
1197
+ end
1198
+ end
1199
+
1200
+ end
1201
+ end
1202
+
1203
+ describe ":as => :hidden" do
1204
+ before do
1205
+ @new_post.stub!(:secret)
1206
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string))
1207
+
1208
+ semantic_form_for(@new_post) do |builder|
1209
+ concat(builder.input(:secret, :as => :hidden))
1210
+ end
1211
+ end
1212
+
1213
+ it "should have a hidden class on the wrapper" do
1214
+ output_buffer.should have_tag('form li.hidden')
1215
+ end
1216
+
1217
+ it 'should have a post_hidden_input id on the wrapper' do
1218
+ output_buffer.should have_tag('form li#post_secret_input')
1219
+ end
1220
+
1221
+ it 'should not generate a label for the input' do
1222
+ output_buffer.should_not have_tag('form li label')
1223
+ end
1224
+
1225
+ it "should generate a input field" do
1226
+ output_buffer.should have_tag("form li input#post_secret")
1227
+ output_buffer.should have_tag("form li input[@type=\"hidden\"]")
1228
+ output_buffer.should have_tag("form li input[@name=\"post[secret]\"]")
1229
+ end
1230
+
1231
+ it "should not render inline errors" do
1232
+ @errors = mock('errors')
1233
+ @errors.stub!(:[]).with(:secret).and_return(["foo", "bah"])
1234
+ @new_post.stub!(:errors).and_return(@errors)
1235
+
1236
+ semantic_form_for(@new_post) do |builder|
1237
+ concat(builder.input(:secret, :as => :hidden))
1238
+ end
1239
+
1240
+ output_buffer.should_not have_tag("form li p.inline-errors")
1241
+ output_buffer.should_not have_tag("form li ul.errors")
1242
+ end
1243
+
1244
+ end
1245
+
1246
+ describe ":as => :time_zone" do
1247
+ before do
1248
+ @new_post.stub!(:time_zone)
1249
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string))
1250
+
1251
+ semantic_form_for(@new_post) do |builder|
1252
+ concat(builder.input(:time_zone))
1253
+ end
1254
+ end
1255
+
1256
+ it "should have a time_zone class on the wrapper" do
1257
+ output_buffer.should have_tag('form li.time_zone')
1258
+ end
1259
+
1260
+ it 'should have a post_title_input id on the wrapper' do
1261
+ output_buffer.should have_tag('form li#post_time_zone_input')
1262
+ end
1263
+
1264
+ it 'should generate a label for the input' do
1265
+ output_buffer.should have_tag('form li label')
1266
+ output_buffer.should have_tag('form li label[@for="post_time_zone"')
1267
+ output_buffer.should have_tag('form li label', /Time zone/)
1268
+ end
1269
+
1270
+ it "should generate a select" do
1271
+ output_buffer.should have_tag("form li select")
1272
+ output_buffer.should have_tag("form li select#post_time_zone")
1273
+ output_buffer.should have_tag("form li select[@name=\"post[time_zone]\"]")
1274
+ end
1275
+
1276
+ it 'should use input_html to style inputs' do
1277
+ semantic_form_for(@new_post) do |builder|
1278
+ concat(builder.input(:time_zone, :input_html => { :class => 'myclass' }))
1279
+ end
1280
+ output_buffer.should have_tag("form li select.myclass")
1281
+ end
1282
+
1283
+ describe 'when no object is given' do
1284
+ before(:each) do
1285
+ semantic_form_for(:project, :url => 'http://test.host/') do |builder|
1286
+ concat(builder.input(:time_zone, :as => :time_zone))
1287
+ end
1288
+ end
1289
+
1290
+ it 'should generate labels' do
1291
+ output_buffer.should have_tag('form li label')
1292
+ output_buffer.should have_tag('form li label[@for="project_time_zone"')
1293
+ output_buffer.should have_tag('form li label', /Time zone/)
1294
+ end
1295
+
1296
+ it 'should generate select inputs' do
1297
+ output_buffer.should have_tag("form li select")
1298
+ output_buffer.should have_tag("form li select#project_time_zone")
1299
+ output_buffer.should have_tag("form li select[@name=\"project[time_zone]\"]")
1300
+ end
1301
+ end
1302
+ end
1303
+
1304
+ describe ":as => :country" do
1305
+
1306
+ before do
1307
+ @new_post.stub!(:country)
1308
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string))
1309
+ end
1310
+
1311
+ describe "when country_select is not available as a helper from a plugin" do
1312
+
1313
+ it "should raise an error, sugesting the author installs a plugin" do
1314
+ lambda {
1315
+ semantic_form_for(@new_post) do |builder|
1316
+ concat(builder.input(:country, :as => :country))
1317
+ end
1318
+ }.should raise_error
1319
+ end
1320
+
1321
+ end
1322
+
1323
+ describe "when country_select is available as a helper (from a plugin)" do
1324
+
1325
+ before do
1326
+ semantic_form_for(@new_post) do |builder|
1327
+ builder.stub!(:country_select).and_return("<select><option>...</option></select>")
1328
+ concat(builder.input(:country, :as => :country))
1329
+ end
1330
+ end
1331
+
1332
+ it "should have a time_zone class on the wrapper" do
1333
+ output_buffer.should have_tag('form li.country')
1334
+ end
1335
+
1336
+ it 'should have a post_title_input id on the wrapper' do
1337
+ output_buffer.should have_tag('form li#post_country_input')
1338
+ end
1339
+
1340
+ it 'should generate a label for the input' do
1341
+ output_buffer.should have_tag('form li label')
1342
+ output_buffer.should have_tag('form li label[@for="post_country"')
1343
+ output_buffer.should have_tag('form li label', /Country/)
1344
+ end
1345
+
1346
+ it "should generate a select" do
1347
+ output_buffer.should have_tag("form li select")
1348
+ end
1349
+
1350
+ end
1351
+
1352
+ describe ":priority_countries option" do
1353
+
1354
+ it "should be passed down to the country_select helper when provided" do
1355
+ priority_countries = ["Foo", "Bah"]
1356
+ semantic_form_for(@new_post) do |builder|
1357
+ builder.stub!(:country_select).and_return("<select><option>...</option></select>")
1358
+ builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return("<select><option>...</option></select>")
1359
+
1360
+ concat(builder.input(:country, :as => :country, :priority_countries => priority_countries))
1361
+ end
1362
+ end
1363
+
1364
+ it "should default to the @@priority_countries config when absent" do
1365
+ priority_countries = Formtastic::SemanticFormBuilder.priority_countries
1366
+ priority_countries.should_not be_empty
1367
+ priority_countries.should_not be_nil
1368
+
1369
+ semantic_form_for(@new_post) do |builder|
1370
+ builder.stub!(:country_select).and_return("<select><option>...</option></select>")
1371
+ builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return("<select><option>...</option></select>")
1372
+
1373
+ concat(builder.input(:country, :as => :country))
1374
+ end
1375
+ end
1376
+
1377
+ end
1378
+
1379
+ end
1380
+
1381
+ describe ':as => :radio' do
1382
+
1383
+ before do
1384
+ @new_post.stub!(:author).and_return(@bob)
1385
+ @new_post.stub!(:author_id).and_return(@bob.id)
1386
+ Post.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Author, :macro => :belongs_to) }
1387
+ end
1388
+
1389
+ describe 'for belongs_to association' do
1390
+ before do
1391
+ semantic_form_for(@new_post) do |builder|
1392
+ concat(builder.input(:author, :as => :radio, :value_as_class => true))
1393
+ end
1394
+ end
1395
+
1396
+ it 'should have a radio class on the wrapper' do
1397
+ output_buffer.should have_tag('form li.radio')
1398
+ end
1399
+
1400
+ it 'should have a post_author_input id on the wrapper' do
1401
+ output_buffer.should have_tag('form li#post_author_input')
1402
+ end
1403
+
1404
+ it 'should generate a fieldset and legend containing label text for the input' do
1405
+ output_buffer.should have_tag('form li fieldset')
1406
+ output_buffer.should have_tag('form li fieldset legend')
1407
+ output_buffer.should have_tag('form li fieldset legend', /Author/)
1408
+ end
1409
+
1410
+ it 'should generate an ordered list with a list item for each choice' do
1411
+ output_buffer.should have_tag('form li fieldset ol')
1412
+ output_buffer.should have_tag('form li fieldset ol li', :count => Author.find(:all).size)
1413
+ end
1414
+
1415
+ it 'should have one option with a "checked" attribute' do
1416
+ output_buffer.should have_tag('form li input[@checked]', :count => 1)
1417
+ end
1418
+
1419
+ describe "each choice" do
1420
+
1421
+ it 'should contain a label for the radio input with a nested input and label text' do
1422
+ Author.find(:all).each do |author|
1423
+ output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/)
1424
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_id_#{author.id}']")
1425
+ end
1426
+ end
1427
+
1428
+ it 'should use values as li.class when value_as_class is true' do
1429
+ Author.find(:all).each do |author|
1430
+ output_buffer.should have_tag("form li fieldset ol li.#{author.id} label")
1431
+ end
1432
+ end
1433
+
1434
+ it "should have a radio input" do
1435
+ Author.find(:all).each do |author|
1436
+ output_buffer.should have_tag("form li fieldset ol li label input#post_author_id_#{author.id}")
1437
+ output_buffer.should have_tag("form li fieldset ol li label input[@type='radio']")
1438
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']")
1439
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='post[author_id]']")
1440
+ end
1441
+ end
1442
+
1443
+ it "should mark input as checked if it's the the existing choice" do
1444
+ @new_post.author_id.should == @bob.id
1445
+ @new_post.author.id.should == @bob.id
1446
+ @new_post.author.should == @bob
1447
+
1448
+ semantic_form_for(@new_post) do |builder|
1449
+ concat(builder.input(:author, :as => :radio))
1450
+ end
1451
+
1452
+ output_buffer.should have_tag("form li fieldset ol li label input[@checked='checked']")
1453
+ end
1454
+ end
1455
+
1456
+ describe 'and no object is given' do
1457
+ before(:each) do
1458
+ output_buffer.replace ''
1459
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
1460
+ concat(builder.input(:author_id, :as => :radio, :collection => Author.find(:all)))
1461
+ end
1462
+ end
1463
+
1464
+ it 'should generate a fieldset with legend' do
1465
+ output_buffer.should have_tag('form li fieldset legend', /Author/)
1466
+ end
1467
+
1468
+ it 'shold generate an li tag for each item in the collection' do
1469
+ output_buffer.should have_tag('form li fieldset ol li', :count => Author.find(:all).size)
1470
+ end
1471
+
1472
+ it 'should generate labels for each item' do
1473
+ Author.find(:all).each do |author|
1474
+ output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/)
1475
+ output_buffer.should have_tag("form li fieldset ol li label[@for='project_author_id_#{author.id}']")
1476
+ end
1477
+ end
1478
+
1479
+ it 'should generate inputs for each item' do
1480
+ Author.find(:all).each do |author|
1481
+ output_buffer.should have_tag("form li fieldset ol li label input#project_author_id_#{author.id}")
1482
+ output_buffer.should have_tag("form li fieldset ol li label input[@type='radio']")
1483
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']")
1484
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='project[author_id]']")
1485
+ end
1486
+ end
1487
+ end
1488
+ end
1489
+ end
1490
+
1491
+ describe ':as => :select' do
1492
+
1493
+ before do
1494
+ @new_post.stub!(:author).and_return(@bob)
1495
+ @new_post.stub!(:author_id).and_return(@bob.id)
1496
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :integer, :limit => 255))
1497
+ end
1498
+
1499
+ describe 'for a belongs_to association' do
1500
+ before do
1501
+ semantic_form_for(@new_post) do |builder|
1502
+ concat(builder.input(:author, :as => :select))
1503
+ end
1504
+ end
1505
+
1506
+ it 'should have a select class on the wrapper' do
1507
+ output_buffer.should have_tag('form li.select')
1508
+ end
1509
+
1510
+ it 'should have a post_author_input id on the wrapper' do
1511
+ output_buffer.should have_tag('form li#post_author_input')
1512
+ end
1513
+
1514
+ it 'should have a label inside the wrapper' do
1515
+ output_buffer.should have_tag('form li label')
1516
+ output_buffer.should have_tag('form li label', /Author/)
1517
+ output_buffer.should have_tag("form li label[@for='post_author_id']")
1518
+ end
1519
+
1520
+ it 'should have a select inside the wrapper' do
1521
+ output_buffer.should have_tag('form li select')
1522
+ output_buffer.should have_tag('form li select#post_author_id')
1523
+ end
1524
+
1525
+ it 'should not create a multi-select' do
1526
+ output_buffer.should_not have_tag('form li select[@multiple]')
1527
+ end
1528
+
1529
+ it 'should create a select without size' do
1530
+ output_buffer.should_not have_tag('form li select[@size]')
1531
+ end
1532
+
1533
+ it 'should have a blank option' do
1534
+ output_buffer.should have_tag("form li select option[@value='']")
1535
+ end
1536
+
1537
+ it 'should have a select option for each Author' do
1538
+ output_buffer.should have_tag('form li select option', :count => Author.find(:all).size + 1)
1539
+ Author.find(:all).each do |author|
1540
+ output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/)
1541
+ end
1542
+ end
1543
+
1544
+ it 'should have one option with a "selected" attribute' do
1545
+ output_buffer.should have_tag('form li select option[@selected]', :count => 1)
1546
+ end
1547
+
1548
+ it 'should not singularize the association name' do
1549
+ @new_post.stub!(:author_status).and_return(@bob)
1550
+ @new_post.stub!(:author_status_id).and_return(@bob.id)
1551
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :integer, :limit => 255))
1552
+
1553
+ semantic_form_for(@new_post) do |builder|
1554
+ concat(builder.input(:author_status, :as => :select))
1555
+ end
1556
+
1557
+ output_buffer.should have_tag('form li select#post_author_status_id')
1558
+ end
1559
+ end
1560
+
1561
+ describe 'for a has_many association' do
1562
+ before do
1563
+ semantic_form_for(@fred) do |builder|
1564
+ concat(builder.input(:posts, :as => :select))
1565
+ end
1566
+ end
1567
+
1568
+ it 'should have a select class on the wrapper' do
1569
+ output_buffer.should have_tag('form li.select')
1570
+ end
1571
+
1572
+ it 'should have a post_author_input id on the wrapper' do
1573
+ output_buffer.should have_tag('form li#author_posts_input')
1574
+ end
1575
+
1576
+ it 'should have a label inside the wrapper' do
1577
+ output_buffer.should have_tag('form li label')
1578
+ output_buffer.should have_tag('form li label', /Post/)
1579
+ output_buffer.should have_tag("form li label[@for='author_post_ids']")
1580
+ end
1581
+
1582
+ it 'should have a select inside the wrapper' do
1583
+ output_buffer.should have_tag('form li select')
1584
+ output_buffer.should have_tag('form li select#author_post_ids')
1585
+ end
1586
+
1587
+ it 'should have a multi-select select' do
1588
+ output_buffer.should have_tag('form li select[@multiple="multiple"]')
1589
+ end
1590
+
1591
+ it 'should have a select option for each Post' do
1592
+ output_buffer.should have_tag('form li select option', :count => Post.find(:all).size)
1593
+ Post.find(:all).each do |post|
1594
+ output_buffer.should have_tag("form li select option[@value='#{post.id}']", /#{post.to_label}/)
1595
+ end
1596
+ end
1597
+
1598
+ it 'should not have a blank option' do
1599
+ output_buffer.should_not have_tag("form li select option[@value='']")
1600
+ end
1601
+
1602
+ it 'should have one option with a "selected" attribute' do
1603
+ output_buffer.should have_tag('form li select option[@selected]', :count => 1)
1604
+ end
1605
+ end
1606
+
1607
+ describe 'for a has_and_belongs_to_many association' do
1608
+ before do
1609
+ semantic_form_for(@freds_post) do |builder|
1610
+ concat(builder.input(:authors, :as => :select))
1611
+ end
1612
+ end
1613
+
1614
+ it 'should have a select class on the wrapper' do
1615
+ output_buffer.should have_tag('form li.select')
1616
+ end
1617
+
1618
+ it 'should have a post_author_input id on the wrapper' do
1619
+ output_buffer.should have_tag('form li#post_authors_input')
1620
+ end
1621
+
1622
+ it 'should have a label inside the wrapper' do
1623
+ output_buffer.should have_tag('form li label')
1624
+ output_buffer.should have_tag('form li label', /Author/)
1625
+ output_buffer.should have_tag("form li label[@for='post_author_ids']")
1626
+ end
1627
+
1628
+ it 'should have a select inside the wrapper' do
1629
+ output_buffer.should have_tag('form li select')
1630
+ output_buffer.should have_tag('form li select#post_author_ids')
1631
+ end
1632
+
1633
+ it 'should have a multi-select select' do
1634
+ output_buffer.should have_tag('form li select[@multiple="multiple"]')
1635
+ end
1636
+
1637
+ it 'should have a select option for each Author' do
1638
+ output_buffer.should have_tag('form li select option', :count => Author.find(:all).size)
1639
+ Author.find(:all).each do |author|
1640
+ output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/)
1641
+ end
1642
+ end
1643
+
1644
+ it 'should not have a blank option' do
1645
+ output_buffer.should_not have_tag("form li select option[@value='']")
1646
+ end
1647
+
1648
+ it 'should have one option with a "selected" attribute' do
1649
+ output_buffer.should have_tag('form li select option[@selected]', :count => 1)
1650
+ end
1651
+ end
1652
+
1653
+ describe 'when :include_blank is not set' do
1654
+ before do
1655
+ @new_post.stub!(:author_id).and_return(nil)
1656
+ semantic_form_for(@new_post) do |builder|
1657
+ concat(builder.input(:author, :as => :select))
1658
+ end
1659
+ end
1660
+
1661
+ it 'should have a blank option by default' do
1662
+ output_buffer.should have_tag("form li select option[@value='']", "")
1663
+ end
1664
+ end
1665
+
1666
+ describe 'when :include_blank is set to false' do
1667
+ before do
1668
+ @new_post.stub!(:author_id).and_return(nil)
1669
+ semantic_form_for(@new_post) do |builder|
1670
+ concat(builder.input(:author, :as => :select, :include_blank => false))
1671
+ end
1672
+ end
1673
+
1674
+ it 'should not have a blank option' do
1675
+ output_buffer.should_not have_tag("form li select option[@value='']", "")
1676
+ end
1677
+ end
1678
+
1679
+ describe 'when :prompt => "choose something" is set' do
1680
+ before do
1681
+ @new_post.stub!(:author_id).and_return(nil)
1682
+ semantic_form_for(@new_post) do |builder|
1683
+ concat(builder.input(:author, :as => :select, :prompt => "choose author"))
1684
+ end
1685
+ end
1686
+
1687
+ it 'should have a select with prompt' do
1688
+ output_buffer.should have_tag("form li select option[@value='']", /choose author/)
1689
+ end
1690
+
1691
+ it 'should not have a blank select option' do
1692
+ output_buffer.should_not have_tag("form li select option[@value='']", "")
1693
+ end
1694
+ end
1695
+
1696
+ describe 'when no object is given' do
1697
+ before(:each) do
1698
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
1699
+ concat(builder.input(:author, :as => :select, :collection => Author.find(:all)))
1700
+ end
1701
+ end
1702
+
1703
+ it 'should generate label' do
1704
+ output_buffer.should have_tag('form li label', /Author/)
1705
+ output_buffer.should have_tag("form li label[@for='project_author']")
1706
+ end
1707
+
1708
+ it 'should generate select inputs' do
1709
+ output_buffer.should have_tag('form li select#project_author')
1710
+ output_buffer.should have_tag('form li select option', :count => Author.find(:all).size + 1)
1711
+ end
1712
+
1713
+ it 'should generate an option to each item' do
1714
+ Author.find(:all).each do |author|
1715
+ output_buffer.should have_tag("form li select option[@value='#{author.id}']", /#{author.to_label}/)
1716
+ end
1717
+ end
1718
+ end
1719
+ end
1720
+
1721
+ describe ':as => :check_boxes' do
1722
+
1723
+ describe 'for a has_many association' do
1724
+ before do
1725
+ semantic_form_for(@fred) do |builder|
1726
+ concat(builder.input(:posts, :as => :check_boxes, :value_as_class => true))
1727
+ end
1728
+ end
1729
+
1730
+ it 'should have a check_boxes class on the wrapper' do
1731
+ output_buffer.should have_tag('form li.check_boxes')
1732
+ end
1733
+
1734
+ it 'should have a author_posts_input id on the wrapper' do
1735
+ output_buffer.should have_tag('form li#author_posts_input')
1736
+ end
1737
+
1738
+ it 'should generate a fieldset and legend containing label text for the input' do
1739
+ output_buffer.should have_tag('form li fieldset')
1740
+ output_buffer.should have_tag('form li fieldset legend')
1741
+ output_buffer.should have_tag('form li fieldset legend', /Posts/)
1742
+ end
1743
+
1744
+ it 'should generate an ordered list with a list item for each choice' do
1745
+ output_buffer.should have_tag('form li fieldset ol')
1746
+ output_buffer.should have_tag('form li fieldset ol li', :count => Post.find(:all).size)
1747
+ end
1748
+
1749
+ it 'should have one option with a "checked" attribute' do
1750
+ output_buffer.should have_tag('form li input[@checked]', :count => 1)
1751
+ end
1752
+
1753
+ it 'should generate hidden inputs with default value blank' do
1754
+ output_buffer.should have_tag("form li fieldset ol li label input[@type='hidden'][@value='']", :count => Post.find(:all).size)
1755
+ end
1756
+
1757
+ describe "each choice" do
1758
+
1759
+ it 'should contain a label for the radio input with a nested input and label text' do
1760
+ Post.find(:all).each do |post|
1761
+ output_buffer.should have_tag('form li fieldset ol li label', /#{post.to_label}/)
1762
+ output_buffer.should have_tag("form li fieldset ol li label[@for='author_post_ids_#{post.id}']")
1763
+ end
1764
+ end
1765
+
1766
+ it 'should use values as li.class when value_as_class is true' do
1767
+ Post.find(:all).each do |post|
1768
+ output_buffer.should have_tag("form li fieldset ol li.#{post.id} label")
1769
+ end
1770
+ end
1771
+
1772
+ it 'should have a checkbox input for each post' do
1773
+ Post.find(:all).each do |post|
1774
+ output_buffer.should have_tag("form li fieldset ol li label input#author_post_ids_#{post.id}")
1775
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='author[post_ids][]']", :count => 2)
1776
+ end
1777
+ end
1778
+
1779
+ it "should mark input as checked if it's the the existing choice" do
1780
+ Post.find(:all).include?(@fred.posts.first).should be_true
1781
+ output_buffer.should have_tag("form li fieldset ol li label input[@checked='checked']")
1782
+ end
1783
+ end
1784
+
1785
+ describe 'and no object is given' do
1786
+ before(:each) do
1787
+ output_buffer.replace ''
1788
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
1789
+ concat(builder.input(:author_id, :as => :check_boxes, :collection => Author.find(:all)))
1790
+ end
1791
+ end
1792
+
1793
+ it 'should generate a fieldset with legend' do
1794
+ output_buffer.should have_tag('form li fieldset legend', /Author/)
1795
+ end
1796
+
1797
+ it 'shold generate an li tag for each item in the collection' do
1798
+ output_buffer.should have_tag('form li fieldset ol li', :count => Author.find(:all).size)
1799
+ end
1800
+
1801
+ it 'should generate labels for each item' do
1802
+ Author.find(:all).each do |author|
1803
+ output_buffer.should have_tag('form li fieldset ol li label', /#{author.to_label}/)
1804
+ output_buffer.should have_tag("form li fieldset ol li label[@for='project_author_id_#{author.id}']")
1805
+ end
1806
+ end
1807
+
1808
+ it 'should generate inputs for each item' do
1809
+ Author.find(:all).each do |author|
1810
+ output_buffer.should have_tag("form li fieldset ol li label input#project_author_id_#{author.id}")
1811
+ output_buffer.should have_tag("form li fieldset ol li label input[@type='checkbox']")
1812
+ output_buffer.should have_tag("form li fieldset ol li label input[@value='#{author.id}']")
1813
+ output_buffer.should have_tag("form li fieldset ol li label input[@name='project[author_id][]']")
1814
+ end
1815
+ end
1816
+ end
1817
+ end
1818
+ end
1819
+
1820
+ describe 'for collections' do
1821
+
1822
+ before do
1823
+ @new_post.stub!(:author).and_return(@bob)
1824
+ @new_post.stub!(:author_id).and_return(@bob.id)
1825
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :integer, :limit => 255))
1826
+ end
1827
+
1828
+ describe 'when the :options option is provided to a :select type' do
1829
+ it "raises an error if the :collection option is also provided" do
1830
+ lambda do
1831
+ semantic_form_for(@new_post) do |builder|
1832
+ builder.input(:author, :as => :select, :options => 'options', :collection => [])
1833
+ end
1834
+ end.should raise_error
1835
+ end
1836
+
1837
+ it "uses the :options value as the content for the select tag" do
1838
+ options = '<option value="Text Value" data-key="custom attribute">Text Content</option>'
1839
+
1840
+ semantic_form_for(@new_post) do |builder|
1841
+ concat(builder.input(:author, :as => :select, :options => options))
1842
+ end
1843
+
1844
+ output_buffer.should have_tag("form li.select select option", "")
1845
+ output_buffer.should have_tag("form li.select select option", "Text Content")
1846
+ end
1847
+ end
1848
+
1849
+ { :select => :option, :radio => :input, :check_boxes => :'input[@type="checkbox"]' }.each do |type, countable|
1850
+
1851
+ describe ":as => #{type.inspect}" do
1852
+ describe 'when the :collection option is not provided' do
1853
+ it 'should perform a basic find on the association class' do
1854
+ Author.should_receive(:find)
1855
+
1856
+ semantic_form_for(@new_post) do |builder|
1857
+ concat(builder.input(:author, :as => type))
1858
+ end
1859
+ end
1860
+
1861
+ it 'should show a deprecation warning if user gives the association using _id' do
1862
+ # Check for deprecation message
1863
+ ::ActiveSupport::Deprecation.should_receive(:warn).with(/association/, anything())
1864
+
1865
+ Author.should_receive(:find)
1866
+ semantic_form_for(@new_post) do |builder|
1867
+ concat(builder.input(:author_id, :as => type))
1868
+ end
1869
+ end
1870
+ end
1871
+
1872
+ describe 'when the :collection option is provided' do
1873
+
1874
+ before do
1875
+ @authors = Author.find(:all) * 2
1876
+ output_buffer.replace '' # clears the output_buffer from the before block, hax!
1877
+ end
1878
+
1879
+ it 'should not call find() on the parent class' do
1880
+ Author.should_not_receive(:find)
1881
+ semantic_form_for(@new_post) do |builder|
1882
+ concat(builder.input(:author, :as => type, :collection => @authors))
1883
+ end
1884
+ end
1885
+
1886
+ it 'should use the provided collection' do
1887
+ semantic_form_for(@new_post) do |builder|
1888
+ concat(builder.input(:author, :as => type, :collection => @authors))
1889
+ end
1890
+ output_buffer.should have_tag("form li.#{type} #{countable}", :count => @authors.size + (type == :select ? 1 : 0))
1891
+ end
1892
+
1893
+ describe 'and the :collection is an array of strings' do
1894
+ before do
1895
+ @new_post.stub!(:category_name).and_return('')
1896
+ @categories = [ 'General', 'Design', 'Development' ]
1897
+ end
1898
+
1899
+ it "should use the string as the label text and value for each #{countable}" do
1900
+ semantic_form_for(@new_post) do |builder|
1901
+ concat(builder.input(:category_name, :as => type, :collection => @categories))
1902
+ end
1903
+
1904
+ @categories.each do |value|
1905
+ output_buffer.should have_tag("form li.#{type}", /#{value}/)
1906
+ output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value}']")
1907
+ end
1908
+ end
1909
+
1910
+ if type == :radio
1911
+ it 'should generate a sanitized label for attribute' do
1912
+ @bob.stub!(:category_name).and_return(@categories)
1913
+ semantic_form_for(@new_post) do |builder|
1914
+ builder.semantic_fields_for(@bob) do |bob_builder|
1915
+ concat(bob_builder.input(:category_name, :as => type, :collection => @categories))
1916
+ end
1917
+ end
1918
+
1919
+ @categories.each do |item|
1920
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_#{item.downcase}']")
1921
+ end
1922
+ end
1923
+ end
1924
+ end
1925
+
1926
+ describe 'and the :collection is a hash of strings' do
1927
+ before do
1928
+ @new_post.stub!(:category_name).and_return('')
1929
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }
1930
+ end
1931
+
1932
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
1933
+ semantic_form_for(@new_post) do |builder|
1934
+ concat(builder.input(:category_name, :as => type, :collection => @categories))
1935
+ end
1936
+
1937
+ @categories.each do |label, value|
1938
+ output_buffer.should have_tag("form li.#{type}", /#{label}/)
1939
+ output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value}']")
1940
+ end
1941
+ end
1942
+ end
1943
+
1944
+ describe 'and the :collection is an array of arrays' do
1945
+ before do
1946
+ @new_post.stub!(:category_name).and_return('')
1947
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }.to_a
1948
+ end
1949
+
1950
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
1951
+ semantic_form_for(@new_post) do |builder|
1952
+ concat(builder.input(:category_name, :as => type, :collection => @categories))
1953
+ end
1954
+
1955
+ @categories.each do |text, value|
1956
+ label = type == :select ? :option : :label
1957
+ output_buffer.should have_tag("form li.#{type} #{label}", /#{text}/i)
1958
+ output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value.to_s}']")
1959
+ end
1960
+ end
1961
+ end
1962
+
1963
+ describe 'and the :collection is an array of symbols' do
1964
+ before do
1965
+ @new_post.stub!(:category_name).and_return('')
1966
+ @categories = [ :General, :Design, :Development ]
1967
+ end
1968
+
1969
+ it "should use the symbol as the label text and value for each #{countable}" do
1970
+ semantic_form_for(@new_post) do |builder|
1971
+ concat(builder.input(:category_name, :as => type, :collection => @categories))
1972
+ end
1973
+
1974
+ @categories.each do |value|
1975
+ label = type == :select ? :option : :label
1976
+ output_buffer.should have_tag("form li.#{type} #{label}", /#{value}/i)
1977
+ output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{value.to_s}']")
1978
+ end
1979
+ end
1980
+ end
1981
+
1982
+ describe 'when the :label_method option is provided' do
1983
+ before do
1984
+ semantic_form_for(@new_post) do |builder|
1985
+ concat(builder.input(:author, :as => type, :label_method => :login))
1986
+ end
1987
+ end
1988
+
1989
+ it 'should have options with text content from the specified method' do
1990
+ Author.find(:all).each do |author|
1991
+ output_buffer.should have_tag("form li.#{type}", /#{author.login}/)
1992
+ end
1993
+ end
1994
+ end
1995
+
1996
+ describe 'when the :label_method option is not provided' do
1997
+ Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
1998
+
1999
+ describe "when the collection objects respond to #{label_method}" do
2000
+ before do
2001
+ @fred.stub!(:respond_to?).and_return { |m| m.to_s == label_method }
2002
+ Author.find(:all).each { |a| a.stub!(label_method).and_return('The Label Text') }
2003
+
2004
+ semantic_form_for(@new_post) do |builder|
2005
+ concat(builder.input(:author, :as => type))
2006
+ end
2007
+ end
2008
+
2009
+ it "should render the options with #{label_method} as the label" do
2010
+ Author.find(:all).each do |author|
2011
+ output_buffer.should have_tag("form li.#{type}", /The Label Text/)
2012
+ end
2013
+ end
2014
+ end
2015
+
2016
+ end
2017
+ end
2018
+
2019
+ describe 'when the :value_method option is provided' do
2020
+ before do
2021
+ semantic_form_for(@new_post) do |builder|
2022
+ concat(builder.input(:author, :as => type, :value_method => :login))
2023
+ end
2024
+ end
2025
+
2026
+ it 'should have options with values from specified method' do
2027
+ Author.find(:all).each do |author|
2028
+ output_buffer.should have_tag("form li.#{type} #{countable}[@value='#{author.login}']")
2029
+ end
2030
+ end
2031
+ end
2032
+
2033
+ end
2034
+ end
2035
+ end
2036
+
2037
+ describe 'for boolean attributes' do
2038
+
2039
+ { :select => :option, :radio => :input }.each do |type, countable|
2040
+ checked_or_selected = { :select => :selected, :radio => :checked }[type]
2041
+
2042
+ describe ":as => #{type.inspect}" do
2043
+
2044
+ before do
2045
+ @new_post.stub!(:allow_comments)
2046
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean))
2047
+
2048
+ semantic_form_for(@new_post) do |builder|
2049
+ concat(builder.input(:allow_comments, :as => type))
2050
+ end
2051
+ end
2052
+
2053
+ it "should have a #{type} class on the wrapper" do
2054
+ output_buffer.should have_tag("form li.#{type}")
2055
+ end
2056
+
2057
+ it 'should have a post_allow_comments_input id on the wrapper' do
2058
+ output_buffer.should have_tag('form li#post_allow_comments_input')
2059
+ end
2060
+
2061
+ it 'should generate a fieldset containing a legend' do
2062
+ output_buffer.should have_tag("form li.#{type}", /Allow comments/)
2063
+ end
2064
+
2065
+ it "should generate two #{countable}" do
2066
+ output_buffer.should have_tag("form li.#{type} #{countable}", :count => (type == :select ? 3 : 2))
2067
+ output_buffer.should have_tag(%{form li.#{type} #{countable}[@value="true"]})
2068
+ output_buffer.should have_tag(%{form li.#{type} #{countable}[@value="false"]})
2069
+ end
2070
+
2071
+ describe 'when the locale sets the label text' do
2072
+ before do
2073
+ I18n.backend.store_translations 'en', :formtastic => {:yes => 'Absolutely!', :no => 'Never!'}
2074
+
2075
+ semantic_form_for(@new_post) do |builder|
2076
+ concat(builder.input(:allow_comments, :as => type))
2077
+ end
2078
+ end
2079
+
2080
+ after do
2081
+ I18n.backend.store_translations 'en', :formtastic => {:yes => nil, :no => nil}
2082
+ end
2083
+
2084
+ it 'should allow translation of the labels' do
2085
+ output_buffer.should have_tag("form li.#{type}", /Absolutely\!/)
2086
+ output_buffer.should have_tag("form li.#{type}", /Never\!/)
2087
+ end
2088
+ end
2089
+
2090
+ describe 'when the value is nil' do
2091
+ before do
2092
+ @new_post.stub!(:allow_comments).and_return(nil)
2093
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean))
2094
+
2095
+ semantic_form_for(@new_post) do |builder|
2096
+ concat(builder.input(:allow_comments, :as => type))
2097
+ end
2098
+ end
2099
+
2100
+ it "should not mark either #{countable} as #{checked_or_selected}" do
2101
+ output_buffer.should_not have_tag(%{form li.#{type} input[@#{checked_or_selected}="#{checked_or_selected}"]})
2102
+ end
2103
+ end
2104
+
2105
+ describe 'when the value is true' do
2106
+ before do
2107
+ @new_post.stub!(:allow_comments).and_return(true)
2108
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean))
2109
+ semantic_form_for(@new_post) do |builder|
2110
+ concat(builder.input(:allow_comments, :as => type))
2111
+ end
2112
+ end
2113
+
2114
+ it "should mark the true #{countable} as #{checked_or_selected}" do
2115
+ output_buffer.should have_tag(%{form li.#{type} #{countable}[@value="true"][@#{checked_or_selected}="#{checked_or_selected}"]}, :count => 1)
2116
+ end
2117
+
2118
+ it "should not mark the false #{countable} as #{checked_or_selected}" do
2119
+ output_buffer.should_not have_tag(%{form li.#{type} #{countable}[@value="false"][@#{checked_or_selected}="#{checked_or_selected}"]})
2120
+ end
2121
+ end
2122
+
2123
+ describe 'when the value is false' do
2124
+ before do
2125
+ @new_post.stub!(:allow_comments).and_return(false)
2126
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean))
2127
+ semantic_form_for(@new_post) do |builder|
2128
+ concat(builder.input(:allow_comments, :as => type))
2129
+ end
2130
+ end
2131
+
2132
+ it "should not mark the true #{countable} as #{checked_or_selected}" do
2133
+ output_buffer.should_not have_tag(%{form li.#{type} #{countable}[@value="true"][@#{checked_or_selected}="#{checked_or_selected}"]})
2134
+ end
2135
+
2136
+ it "should mark the false #{countable} as #{checked_or_selected}" do
2137
+ output_buffer.should have_tag(%{form li.#{type} #{countable}[@value="false"][@#{checked_or_selected}="#{checked_or_selected}"]}, :count => 1)
2138
+ end
2139
+ end
2140
+
2141
+ describe 'when :true and :false options are provided' do
2142
+ before do
2143
+ @new_post.stub!(:allow_comments)
2144
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean))
2145
+ semantic_form_for(@new_post) do |builder|
2146
+ concat(builder.input(:allow_comments, :as => type, :true => "Absolutely", :false => "No Way"))
2147
+ end
2148
+ end
2149
+
2150
+ it 'should use them as labels' do
2151
+ output_buffer.should have_tag("form li.#{type}", /Absolutely/)
2152
+ output_buffer.should have_tag("form li.#{type}", /No Way/)
2153
+ end
2154
+ end
2155
+ end
2156
+
2157
+ end
2158
+ end
2159
+ end
2160
+
2161
+ describe ':as => :date' do
2162
+
2163
+ before do
2164
+ @new_post.stub!(:publish_at)
2165
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :date))
2166
+
2167
+ semantic_form_for(@new_post) do |@builder|
2168
+ concat(@builder.input(:publish_at, :as => :date))
2169
+ end
2170
+ end
2171
+
2172
+ it 'should have a date class on the wrapper li' do
2173
+ output_buffer.should have_tag('form li.date')
2174
+ end
2175
+
2176
+ it 'should have a fieldset inside the li wrapper' do
2177
+ output_buffer.should have_tag('form li.date fieldset')
2178
+ end
2179
+
2180
+ it 'should have a legend containing the label text inside the fieldset' do
2181
+ output_buffer.should have_tag('form li.date fieldset legend', /Publish at/)
2182
+ end
2183
+
2184
+ it 'should have an ordered list of three items inside the fieldset' do
2185
+ output_buffer.should have_tag('form li.date fieldset ol')
2186
+ output_buffer.should have_tag('form li.date fieldset ol li', :count => 3)
2187
+ end
2188
+
2189
+ it 'should have three labels for year, month and day' do
2190
+ output_buffer.should have_tag('form li.date fieldset ol li label', :count => 3)
2191
+ output_buffer.should have_tag('form li.date fieldset ol li label', /year/i)
2192
+ output_buffer.should have_tag('form li.date fieldset ol li label', /month/i)
2193
+ output_buffer.should have_tag('form li.date fieldset ol li label', /day/i)
2194
+ end
2195
+
2196
+ it 'should have three selects for year, month and day' do
2197
+ output_buffer.should have_tag('form li.date fieldset ol li select', :count => 3)
2198
+ end
2199
+ end
2200
+
2201
+ describe ':as => :datetime' do
2202
+
2203
+ before do
2204
+ @new_post.stub!(:publish_at)
2205
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :datetime))
2206
+
2207
+ semantic_form_for(@new_post) do |builder|
2208
+ concat(builder.input(:publish_at, :as => :datetime))
2209
+ end
2210
+ end
2211
+
2212
+ it 'should have a datetime class on the wrapper li' do
2213
+ output_buffer.should have_tag('form li.datetime')
2214
+ end
2215
+
2216
+ it 'should have a fieldset inside the li wrapper' do
2217
+ output_buffer.should have_tag('form li.datetime fieldset')
2218
+ end
2219
+
2220
+ it 'should have a legend containing the label text inside the fieldset' do
2221
+ output_buffer.should have_tag('form li.datetime fieldset legend', /Publish at/)
2222
+ end
2223
+
2224
+ it 'should have an ordered list of five items inside the fieldset' do
2225
+ output_buffer.should have_tag('form li.datetime fieldset ol')
2226
+ output_buffer.should have_tag('form li.datetime fieldset ol li', :count => 5)
2227
+ end
2228
+
2229
+ it 'should have five labels for year, month, day, hour and minute' do
2230
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', :count => 5)
2231
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /year/i)
2232
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /month/i)
2233
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /day/i)
2234
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /hour/i)
2235
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /minute/i)
2236
+ end
2237
+
2238
+ it 'should have five selects for year, month, day, hour and minute' do
2239
+ output_buffer.should have_tag('form li.datetime fieldset ol li select', :count => 5)
2240
+ end
2241
+
2242
+ it 'should generate a sanitized label and matching ids for attribute' do
2243
+ @bob.stub!(:publish_at)
2244
+ @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :datetime))
2245
+
2246
+ semantic_form_for(@new_post) do |builder|
2247
+ builder.semantic_fields_for(@bob, :index => 10) do |bob_builder|
2248
+ concat(bob_builder.input(:publish_at, :as => :datetime))
2249
+ end
2250
+ end
2251
+
2252
+ 1.upto(5) do |i|
2253
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_10_publish_at_#{i}i']")
2254
+ output_buffer.should have_tag("form li fieldset ol li #post_author_10_publish_at_#{i}i")
2255
+ end
2256
+ end
2257
+
2258
+ describe 'when :discard_input => true is set' do
2259
+ it 'should use default hidden value equals to 1 when attribute returns nil' do
2260
+ semantic_form_for(@new_post) do |builder|
2261
+ concat(builder.input(:publish_at, :as => :datetime, :discard_day => true))
2262
+ end
2263
+
2264
+ output_buffer.should have_tag("form li input[@type='hidden'][@value='1']")
2265
+ end
2266
+
2267
+ it 'should use default attribute value when it is not nil' do
2268
+ @new_post.stub!(:publish_at).and_return(Date.new(2007,12,27))
2269
+ semantic_form_for(@new_post) do |builder|
2270
+ concat(builder.input(:publish_at, :as => :datetime, :discard_day => true))
2271
+ end
2272
+
2273
+ output_buffer.should have_tag("form li input[@type='hidden'][@value='27']")
2274
+ end
2275
+ end
2276
+
2277
+ describe 'when :include_blank => true is set' do
2278
+ before do
2279
+ semantic_form_for(@new_post) do |builder|
2280
+ concat(builder.input(:publish_at, :as => :datetime, :include_blank => true))
2281
+ end
2282
+ end
2283
+
2284
+ it 'should have a blank select option' do
2285
+ output_buffer.should have_tag("option[@value='']", "")
2286
+ end
2287
+ end
2288
+
2289
+ describe 'inputs order' do
2290
+ it 'should have a default' do
2291
+ semantic_form_for(@new_post) do |builder|
2292
+ self.should_receive(:select_year).once.ordered.and_return('')
2293
+ self.should_receive(:select_month).once.ordered.and_return('')
2294
+ self.should_receive(:select_day).once.ordered.and_return('')
2295
+ builder.input(:publish_at, :as => :datetime)
2296
+ end
2297
+ end
2298
+
2299
+ it 'should be specified with :order option' do
2300
+ I18n.backend.store_translations 'en', :date => { :order => [:month, :year, :day] }
2301
+ semantic_form_for(@new_post) do |builder|
2302
+ self.should_receive(:select_month).once.ordered.and_return('')
2303
+ self.should_receive(:select_year).once.ordered.and_return('')
2304
+ self.should_receive(:select_day).once.ordered.and_return('')
2305
+ builder.input(:publish_at, :as => :datetime)
2306
+ end
2307
+ end
2308
+
2309
+ it 'should be changed through I18n' do
2310
+ semantic_form_for(@new_post) do |builder|
2311
+ self.should_receive(:select_day).once.ordered.and_return('')
2312
+ self.should_receive(:select_month).once.ordered.and_return('')
2313
+ self.should_receive(:select_year).once.ordered.and_return('')
2314
+ builder.input(:publish_at, :as => :datetime, :order => [:day, :month, :year])
2315
+ end
2316
+ end
2317
+ end
2318
+
2319
+ describe 'when the locale changes the label text' do
2320
+ before do
2321
+ I18n.backend.store_translations 'en', :datetime => {:prompts => {
2322
+ :year => 'The Year', :month => 'The Month', :day => 'The Day',
2323
+ :hour => 'The Hour', :minute => 'The Minute'
2324
+ }}
2325
+ semantic_form_for(@new_post) do |builder|
2326
+ concat(builder.input(:publish_at, :as => :datetime))
2327
+ end
2328
+ end
2329
+
2330
+ after do
2331
+ I18n.backend.store_translations 'en', :formtastic => {
2332
+ :year => nil, :month => nil, :day => nil,
2333
+ :hour => nil, :minute => nil
2334
+ }
2335
+ end
2336
+
2337
+ it 'should have translated labels for year, month, day, hour and minute' do
2338
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /The Year/)
2339
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /The Month/)
2340
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /The Day/)
2341
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /The Hour/)
2342
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', /The Minute/)
2343
+ end
2344
+ end
2345
+
2346
+ describe 'when no object is given' do
2347
+ before(:each) do
2348
+ output_buffer.replace ''
2349
+ semantic_form_for(:project, :url => 'http://test.host') do |@builder|
2350
+ concat(@builder.input(:publish_at, :as => :datetime))
2351
+ end
2352
+ end
2353
+
2354
+ it 'should have fieldset with legend' do
2355
+ output_buffer.should have_tag('form li.datetime fieldset legend', /Publish at/)
2356
+ end
2357
+
2358
+ it 'should have labels for each input' do
2359
+ output_buffer.should have_tag('form li.datetime fieldset ol li label', :count => 5)
2360
+ end
2361
+
2362
+ it 'should have selects for each inputs' do
2363
+ output_buffer.should have_tag('form li.datetime fieldset ol li select', :count => 5)
2364
+ end
2365
+ end
2366
+ end
2367
+
2368
+ describe ':as => :time' do
2369
+ before do
2370
+ @new_post.stub!(:publish_at)
2371
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :time))
2372
+
2373
+ semantic_form_for(@new_post) do |builder|
2374
+ concat(builder.input(:publish_at, :as => :time))
2375
+ end
2376
+ end
2377
+
2378
+ it 'should have a time class on the wrapper li' do
2379
+ output_buffer.should have_tag('form li.time')
2380
+ end
2381
+
2382
+ it 'should have a fieldset inside the li wrapper' do
2383
+ output_buffer.should have_tag('form li.time fieldset')
2384
+ end
2385
+
2386
+ it 'should have a legend containing the label text inside the fieldset' do
2387
+ output_buffer.should have_tag('form li.time fieldset legend', /Publish at/)
2388
+ end
2389
+
2390
+ it 'should have an ordered list of two items inside the fieldset' do
2391
+ output_buffer.should have_tag('form li.time fieldset ol')
2392
+ output_buffer.should have_tag('form li.time fieldset ol li', :count => 2)
2393
+ end
2394
+
2395
+ it 'should have five labels for hour and minute' do
2396
+ output_buffer.should have_tag('form li.time fieldset ol li label', :count => 2)
2397
+ output_buffer.should have_tag('form li.time fieldset ol li label', /hour/i)
2398
+ output_buffer.should have_tag('form li.time fieldset ol li label', /minute/i)
2399
+ end
2400
+
2401
+ it 'should have two selects for hour and minute' do
2402
+ #output_buffer.should have_tag('form li.time fieldset ol li select', :count => 2)
2403
+ output_buffer.should have_tag('form li.time fieldset ol li', :count => 2)
2404
+ end
2405
+ end
2406
+
2407
+ [:boolean_select, :boolean_radio].each do |type|
2408
+ describe ":as => #{type.inspect}" do
2409
+ it 'should show a deprecation warning' do
2410
+ @new_post.stub!(:allow_comments)
2411
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean))
2412
+
2413
+ ::ActiveSupport::Deprecation.should_receive(:warn).with(/select|radio/, anything())
2414
+
2415
+ semantic_form_for(@new_post) do |builder|
2416
+ concat(builder.input(:allow_comments, :as => type))
2417
+ end
2418
+ end
2419
+ end
2420
+ end
2421
+
2422
+ describe ':as => :boolean' do
2423
+
2424
+ before do
2425
+ @new_post.stub!(:allow_comments)
2426
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :boolean))
2427
+
2428
+ semantic_form_for(@new_post) do |builder|
2429
+ concat(builder.input(:allow_comments, :as => :boolean))
2430
+ end
2431
+ end
2432
+
2433
+ it 'should have a boolean class on the wrapper' do
2434
+ output_buffer.should have_tag('form li.boolean')
2435
+ end
2436
+
2437
+ it 'should have a post_allow_comments_input id on the wrapper' do
2438
+ output_buffer.should have_tag('form li#post_allow_comments_input')
2439
+ end
2440
+
2441
+ it 'should generate a label containing the input' do
2442
+ output_buffer.should have_tag('form li label')
2443
+ output_buffer.should have_tag('form li label[@for="post_allow_comments"')
2444
+ output_buffer.should have_tag('form li label', /Allow comments/)
2445
+ output_buffer.should have_tag('form li label input[@type="checkbox"]')
2446
+ end
2447
+
2448
+ it 'should generate a checkbox input' do
2449
+ output_buffer.should have_tag('form li label input')
2450
+ output_buffer.should have_tag('form li label input#post_allow_comments')
2451
+ output_buffer.should have_tag('form li label input[@type="checkbox"]')
2452
+ output_buffer.should have_tag('form li label input[@name="post[allow_comments]"]')
2453
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="1"]')
2454
+ end
2455
+
2456
+ it 'should allow checked and unchecked values to be sent' do
2457
+ semantic_form_for(@new_post) do |builder|
2458
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'checked', :unchecked_value => 'unchecked'))
2459
+ end
2460
+
2461
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="checked"]')
2462
+ output_buffer.should have_tag('form li label input[@type="hidden"][@value="unchecked"]')
2463
+ end
2464
+
2465
+ it 'should generate a label and a checkbox even if no object is given' do
2466
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
2467
+ concat(builder.input(:allow_comments, :as => :boolean))
2468
+ end
2469
+
2470
+ output_buffer.should have_tag('form li label[@for="project_allow_comments"')
2471
+ output_buffer.should have_tag('form li label', /Allow comments/)
2472
+ output_buffer.should have_tag('form li label input[@type="checkbox"]')
2473
+
2474
+ output_buffer.should have_tag('form li label input#project_allow_comments')
2475
+ output_buffer.should have_tag('form li label input[@type="checkbox"]')
2476
+ output_buffer.should have_tag('form li label input[@name="project[allow_comments]"]')
2477
+ end
2478
+
2479
+ end
2480
+ end
2481
+
2482
+ describe '#inputs' do
2483
+
2484
+ describe 'with a block' do
2485
+
2486
+ describe 'when no options are provided' do
2487
+ before do
2488
+ output_buffer.replace 'before_builder' # clear the output buffer and sets before_builder
2489
+ semantic_form_for(@new_post) do |builder|
2490
+ @inputs_output = builder.inputs do
2491
+ concat('hello')
2492
+ end
2493
+ end
2494
+ end
2495
+
2496
+ it 'should output just the content wrapped in inputs, not the whole template' do
2497
+ output_buffer.should =~ /before_builder/
2498
+ @inputs_output.should_not =~ /before_builder/
2499
+ end
2500
+
2501
+ it 'should render a fieldset inside the form, with a class of "inputs"' do
2502
+ output_buffer.should have_tag("form fieldset.inputs")
2503
+ end
2504
+
2505
+ it 'should render an ol inside the fieldset' do
2506
+ output_buffer.should have_tag("form fieldset.inputs ol")
2507
+ end
2508
+
2509
+ it 'should render the contents of the block inside the ol' do
2510
+ output_buffer.should have_tag("form fieldset.inputs ol", /hello/)
2511
+ end
2512
+
2513
+ it 'should not render a legend inside the fieldset' do
2514
+ output_buffer.should_not have_tag("form fieldset.inputs legend")
2515
+ end
2516
+
2517
+ it 'should render a fieldset even if no object is given' do
2518
+ semantic_form_for(:project, :url => 'http://test.host/') do |builder|
2519
+ @inputs_output = builder.inputs do
2520
+ concat('bye')
2521
+ end
2522
+ end
2523
+
2524
+ output_buffer.should have_tag("form fieldset.inputs ol", /bye/)
2525
+ end
2526
+ end
2527
+
2528
+ describe 'when a :for option is provided' do
2529
+ it 'should render nested inputs' do
2530
+ @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
2531
+
2532
+ semantic_form_for(@new_post) do |builder|
2533
+ builder.inputs :for => [:author, @bob] do |bob_builder|
2534
+ concat(bob_builder.input(:login))
2535
+ end
2536
+ end
2537
+
2538
+ output_buffer.should have_tag("form fieldset.inputs #post_author_login")
2539
+ output_buffer.should_not have_tag("form fieldset.inputs #author_login")
2540
+ end
2541
+
2542
+ it 'should raise an error if :for and block with no argument is given' do
2543
+ semantic_form_for(@new_post) do |builder|
2544
+ proc {
2545
+ builder.inputs(:for => [:author, @bob]) do
2546
+ #
2547
+ end
2548
+ }.should raise_error(ArgumentError, 'You gave :for option with a block to inputs method, ' <<
2549
+ 'but the block does not accept any argument.')
2550
+ end
2551
+ end
2552
+
2553
+ it 'should pass options down to semantic_fields_for' do
2554
+ @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
2555
+
2556
+ semantic_form_for(@new_post) do |builder|
2557
+ builder.inputs :for => [:author, @bob], :for_options => { :index => 10 } do |bob_builder|
2558
+ concat(bob_builder.input(:login))
2559
+ end
2560
+ end
2561
+
2562
+ output_buffer.should have_tag('form fieldset ol li #post_author_10_login')
2563
+ end
2564
+
2565
+ it 'should not add builder as a fieldset attribute tag' do
2566
+ semantic_form_for(@new_post) do |builder|
2567
+ builder.inputs :for => [:author, @bob], :for_options => { :index => 10 } do |bob_builder|
2568
+ concat('input')
2569
+ end
2570
+ end
2571
+
2572
+ output_buffer.should_not have_tag('fieldset[@builder="Formtastic::SemanticFormHelper"]')
2573
+ end
2574
+
2575
+ it 'should send parent_builder as an option to allow child index interpolation' do
2576
+ semantic_form_for(@new_post) do |builder|
2577
+ builder.instance_variable_set('@nested_child_index', 0)
2578
+ builder.inputs :for => [:author, @bob], :name => 'Author #%i' do |bob_builder|
2579
+ concat('input')
2580
+ end
2581
+ end
2582
+
2583
+ output_buffer.should have_tag('fieldset legend', 'Author #1')
2584
+ end
2585
+
2586
+ it 'should also provide child index interpolation when nested child index is a hash' do
2587
+ semantic_form_for(@new_post) do |builder|
2588
+ builder.instance_variable_set('@nested_child_index', :author => 10)
2589
+ builder.inputs :for => [:author, @bob], :name => 'Author #%i' do |bob_builder|
2590
+ concat('input')
2591
+ end
2592
+ end
2593
+
2594
+ output_buffer.should have_tag('fieldset legend', 'Author #11')
2595
+ end
2596
+ end
2597
+
2598
+ describe 'when a :name option is provided' do
2599
+ before do
2600
+ @legend_text = "Advanced options"
2601
+
2602
+ semantic_form_for(@new_post) do |builder|
2603
+ builder.inputs :name => @legend_text do
2604
+ end
2605
+ end
2606
+ end
2607
+
2608
+ it 'should render a fieldset inside the form' do
2609
+ output_buffer.should have_tag("form fieldset legend", /#{@legend_text}/)
2610
+ end
2611
+ end
2612
+
2613
+ describe 'when other options are provided' do
2614
+ before do
2615
+ @id_option = 'advanced'
2616
+ @class_option = 'wide'
2617
+
2618
+ semantic_form_for(@new_post) do |builder|
2619
+ builder.inputs :id => @id_option, :class => @class_option do
2620
+ end
2621
+ end
2622
+ end
2623
+
2624
+ it 'should pass the options into the fieldset tag as attributes' do
2625
+ output_buffer.should have_tag("form fieldset##{@id_option}")
2626
+ output_buffer.should have_tag("form fieldset.#{@class_option}")
2627
+ end
2628
+ end
2629
+
2630
+ end
2631
+
2632
+ describe 'without a block' do
2633
+
2634
+ before do
2635
+ Post.stub!(:reflections).and_return({:author => mock('reflection', :options => {}, :macro => :belongs_to),
2636
+ :comments => mock('reflection', :options => {}, :macro => :has_many) })
2637
+ Post.stub!(:content_columns).and_return([mock('column', :name => 'title'), mock('column', :name => 'body'), mock('column', :name => 'created_at')])
2638
+ Author.stub!(:find).and_return([@fred, @bob])
2639
+
2640
+ @new_post.stub!(:title)
2641
+ @new_post.stub!(:body)
2642
+ @new_post.stub!(:author_id)
2643
+
2644
+ @new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 255))
2645
+ @new_post.stub!(:column_for_attribute).with(:body).and_return(mock('column', :type => :text))
2646
+ @new_post.stub!(:column_for_attribute).with(:created_at).and_return(mock('column', :type => :datetime))
2647
+ @new_post.stub!(:column_for_attribute).with(:author).and_return(nil)
2648
+ end
2649
+
2650
+ describe 'with no args' do
2651
+ before do
2652
+ semantic_form_for(@new_post) do |builder|
2653
+ concat(builder.inputs)
2654
+ end
2655
+ end
2656
+
2657
+ it 'should render a form' do
2658
+ output_buffer.should have_tag('form')
2659
+ end
2660
+
2661
+ it 'should render a fieldset inside the form' do
2662
+ output_buffer.should have_tag('form > fieldset.inputs')
2663
+ end
2664
+
2665
+ it 'should not render a legend in the fieldset' do
2666
+ output_buffer.should_not have_tag('form > fieldset.inputs > legend')
2667
+ end
2668
+
2669
+ it 'should render an ol in the fieldset' do
2670
+ output_buffer.should have_tag('form > fieldset.inputs > ol')
2671
+ end
2672
+
2673
+ it 'should render a list item in the ol for each column and reflection' do
2674
+ # Remove the :has_many macro and :created_at column
2675
+ count = Post.content_columns.size + Post.reflections.size - 2
2676
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li', :count => count)
2677
+ end
2678
+
2679
+ it 'should render a string list item for title' do
2680
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li.string')
2681
+ end
2682
+
2683
+ it 'should render a text list item for body' do
2684
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li.text')
2685
+ end
2686
+
2687
+ it 'should render a select list item for author_id' do
2688
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li.select', :count => 1)
2689
+ end
2690
+
2691
+ it 'should not render timestamps inputs by default' do
2692
+ output_buffer.should_not have_tag('form > fieldset.inputs > ol > li.datetime')
2693
+ end
2694
+ end
2695
+
2696
+ describe 'with column names as args' do
2697
+ describe 'and an object is given' do
2698
+ it 'should render a form with a fieldset containing two list items' do
2699
+ semantic_form_for(@new_post) do |builder|
2700
+ concat(builder.inputs(:title, :body))
2701
+ end
2702
+
2703
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li', :count => 2)
2704
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li.string')
2705
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li.text')
2706
+ end
2707
+ end
2708
+
2709
+ describe 'and no object is given' do
2710
+ it 'should render a form with a fieldset containing two list items' do
2711
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
2712
+ concat(builder.inputs(:title, :body))
2713
+ end
2714
+
2715
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li.string', :count => 2)
2716
+ end
2717
+ end
2718
+ end
2719
+
2720
+ describe 'when a :for option is provided' do
2721
+ describe 'and an object is given' do
2722
+ it 'should render nested inputs' do
2723
+ @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
2724
+
2725
+ semantic_form_for(@new_post) do |builder|
2726
+ concat(builder.inputs(:login, :for => @bob))
2727
+ end
2728
+
2729
+ output_buffer.should have_tag("form fieldset.inputs #post_author_login")
2730
+ output_buffer.should_not have_tag("form fieldset.inputs #author_login")
2731
+ end
2732
+ end
2733
+
2734
+ describe 'and no object is given' do
2735
+ it 'should render nested inputs' do
2736
+ semantic_form_for(:project, :url => 'http://test.host/') do |builder|
2737
+ concat(builder.inputs(:login, :for => @bob))
2738
+ end
2739
+
2740
+ output_buffer.should have_tag("form fieldset.inputs #project_author_login")
2741
+ output_buffer.should_not have_tag("form fieldset.inputs #project_login")
2742
+ end
2743
+ end
2744
+ end
2745
+
2746
+ describe 'with column names and an options hash as args' do
2747
+ before do
2748
+ semantic_form_for(@new_post) do |builder|
2749
+ concat(builder.inputs(:title, :body, :name => "Legendary Legend Text", :id => "my-id"))
2750
+ end
2751
+ end
2752
+
2753
+ it 'should render a form with a fieldset containing two list items' do
2754
+ output_buffer.should have_tag('form > fieldset.inputs > ol > li', :count => 2)
2755
+ end
2756
+
2757
+ it 'should pass the options down to the fieldset' do
2758
+ output_buffer.should have_tag('form > fieldset#my-id.inputs')
2759
+ end
2760
+
2761
+ it 'should use the special :name option as a text for the legend tag' do
2762
+ output_buffer.should have_tag('form > fieldset#my-id.inputs > legend', /Legendary Legend Text/)
2763
+ end
2764
+ end
2765
+
2766
+ end
2767
+
2768
+ end
2769
+
2770
+ describe '#buttons' do
2771
+
2772
+ describe 'with a block' do
2773
+ describe 'when no options are provided' do
2774
+ before do
2775
+ semantic_form_for(@new_post) do |builder|
2776
+ builder.buttons do
2777
+ concat('hello')
2778
+ end
2779
+ end
2780
+ end
2781
+
2782
+ it 'should render a fieldset inside the form, with a class of "inputs"' do
2783
+ output_buffer.should have_tag("form fieldset.buttons")
2784
+ end
2785
+
2786
+ it 'should render an ol inside the fieldset' do
2787
+ output_buffer.should have_tag("form fieldset.buttons ol")
2788
+ end
2789
+
2790
+ it 'should render the contents of the block inside the ol' do
2791
+ output_buffer.should have_tag("form fieldset.buttons ol", /hello/)
2792
+ end
2793
+
2794
+ it 'should not render a legend inside the fieldset' do
2795
+ output_buffer.should_not have_tag("form fieldset.buttons legend")
2796
+ end
2797
+ end
2798
+
2799
+ describe 'when a :name option is provided' do
2800
+ before do
2801
+ @legend_text = "Advanced options"
2802
+
2803
+ semantic_form_for(@new_post) do |builder|
2804
+ builder.buttons :name => @legend_text do
2805
+ end
2806
+ end
2807
+ end
2808
+ it 'should render a fieldset inside the form' do
2809
+ output_buffer.should have_tag("form fieldset legend", /#{@legend_text}/)
2810
+ end
2811
+ end
2812
+
2813
+ describe 'when other options are provided' do
2814
+ before do
2815
+ @id_option = 'advanced'
2816
+ @class_option = 'wide'
2817
+
2818
+ semantic_form_for(@new_post) do |builder|
2819
+ builder.buttons :id => @id_option, :class => @class_option do
2820
+ end
2821
+ end
2822
+ end
2823
+ it 'should pass the options into the fieldset tag as attributes' do
2824
+ output_buffer.should have_tag("form fieldset##{@id_option}")
2825
+ output_buffer.should have_tag("form fieldset.#{@class_option}")
2826
+ end
2827
+ end
2828
+
2829
+ end
2830
+
2831
+ describe 'without a block' do
2832
+
2833
+ describe 'with no args (default buttons)' do
2834
+
2835
+ before do
2836
+ semantic_form_for(@new_post) do |builder|
2837
+ concat(builder.buttons)
2838
+ end
2839
+ end
2840
+
2841
+ it 'should render a form' do
2842
+ output_buffer.should have_tag('form')
2843
+ end
2844
+
2845
+ it 'should render a buttons fieldset inside the form' do
2846
+ output_buffer.should have_tag('form fieldset.buttons')
2847
+ end
2848
+
2849
+ it 'should not render a legend in the fieldset' do
2850
+ output_buffer.should_not have_tag('form fieldset.buttons legend')
2851
+ end
2852
+
2853
+ it 'should render an ol in the fieldset' do
2854
+ output_buffer.should have_tag('form fieldset.buttons ol')
2855
+ end
2856
+
2857
+ it 'should render a list item in the ol for each default button' do
2858
+ output_buffer.should have_tag('form fieldset.buttons ol li', :count => 1)
2859
+ end
2860
+
2861
+ it 'should render a commit list item for the commit button' do
2862
+ output_buffer.should have_tag('form fieldset.buttons ol li.commit')
2863
+ end
2864
+
2865
+ end
2866
+
2867
+ describe 'with button names as args' do
2868
+
2869
+ before do
2870
+ semantic_form_for(@new_post) do |builder|
2871
+ concat(builder.buttons(:commit))
2872
+ end
2873
+ end
2874
+
2875
+ it 'should render a form with a fieldset containing a list item for each button arg' do
2876
+ output_buffer.should have_tag('form > fieldset.buttons > ol > li', :count => 1)
2877
+ output_buffer.should have_tag('form > fieldset.buttons > ol > li.commit')
2878
+ end
2879
+
2880
+ end
2881
+
2882
+ describe 'with button names as args and an options hash' do
2883
+
2884
+ before do
2885
+ semantic_form_for(@new_post) do |builder|
2886
+ concat(builder.buttons(:commit, :name => "Now click a button", :id => "my-id"))
2887
+ end
2888
+ end
2889
+
2890
+ it 'should render a form with a fieldset containing a list item for each button arg' do
2891
+ output_buffer.should have_tag('form > fieldset.buttons > ol > li', :count => 1)
2892
+ output_buffer.should have_tag('form > fieldset.buttons > ol > li.commit', :count => 1)
2893
+ end
2894
+
2895
+ it 'should pass the options down to the fieldset' do
2896
+ output_buffer.should have_tag('form > fieldset#my-id.buttons')
2897
+ end
2898
+
2899
+ it 'should use the special :name option as a text for the legend tag' do
2900
+ output_buffer.should have_tag('form > fieldset#my-id.buttons > legend', /Now click a button/)
2901
+ end
2902
+
2903
+ end
2904
+
2905
+ end
2906
+
2907
+ end
2908
+
2909
+ describe '#commit_button' do
2910
+
2911
+ describe 'when used on any record' do
2912
+
2913
+ before do
2914
+ @new_post.stub!(:new_record?).and_return(false)
2915
+ semantic_form_for(@new_post) do |builder|
2916
+ concat(builder.commit_button)
2917
+ end
2918
+ end
2919
+
2920
+ it 'should render a commit li' do
2921
+ output_buffer.should have_tag('li.commit')
2922
+ end
2923
+
2924
+ it 'should render an input with a type attribute of "submit"' do
2925
+ output_buffer.should have_tag('li.commit input[@type="submit"]')
2926
+ end
2927
+
2928
+ it 'should render an input with a name attribute of "commit"' do
2929
+ output_buffer.should have_tag('li.commit input[@name="commit"]')
2930
+ end
2931
+
2932
+ it 'should pass options given in :button_html to the button' do
2933
+ @new_post.stub!(:new_record?).and_return(false)
2934
+ semantic_form_for(@new_post) do |builder|
2935
+ concat(builder.commit_button('text', :button_html => {:class => 'my_class', :id => 'my_id'}))
2936
+ end
2937
+
2938
+ output_buffer.should have_tag('li.commit input#my_id')
2939
+ output_buffer.should have_tag('li.commit input.my_class')
2940
+ end
2941
+
2942
+ end
2943
+
2944
+ describe 'when the first option is a string and the second is a hash' do
2945
+
2946
+ before do
2947
+ @new_post.stub!(:new_record?).and_return(false)
2948
+ semantic_form_for(@new_post) do |builder|
2949
+ concat(builder.commit_button("a string", :button_html => { :class => "pretty"}))
2950
+ end
2951
+ end
2952
+
2953
+ it "should render the string as the value of the button" do
2954
+ output_buffer.should have_tag('li input[@value="a string"]')
2955
+ end
2956
+
2957
+ it "should deal with the options hash" do
2958
+ output_buffer.should have_tag('li input.pretty')
2959
+ end
2960
+
2961
+ end
2962
+
2963
+ describe 'when the first option is a hash' do
2964
+
2965
+ before do
2966
+ @new_post.stub!(:new_record?).and_return(false)
2967
+ semantic_form_for(@new_post) do |builder|
2968
+ concat(builder.commit_button(:button_html => { :class => "pretty"}))
2969
+ end
2970
+ end
2971
+
2972
+ it "should deal with the options hash" do
2973
+ output_buffer.should have_tag('li input.pretty')
2974
+ end
2975
+
2976
+ end
2977
+
2978
+ describe 'when used on an existing record' do
2979
+
2980
+ it 'should render an input with a value attribute of "Save Post"' do
2981
+ @new_post.stub!(:new_record?).and_return(false)
2982
+ semantic_form_for(@new_post) do |builder|
2983
+ concat(builder.commit_button)
2984
+ end
2985
+ output_buffer.should have_tag('li.commit input[@value="Save Post"]')
2986
+ end
2987
+
2988
+ describe 'when the locale sets the label text' do
2989
+ before do
2990
+ I18n.backend.store_translations 'en', :formtastic => {:save => 'Save Changes To' }
2991
+ @new_post.stub!(:new_record?).and_return(false)
2992
+ semantic_form_for(@new_post) do |builder|
2993
+ concat(builder.commit_button)
2994
+ end
2995
+ end
2996
+
2997
+ after do
2998
+ I18n.backend.store_translations 'en', :formtastic => {:save => nil}
2999
+ end
3000
+
3001
+ it 'should allow translation of the labels' do
3002
+ output_buffer.should have_tag('li.commit input[@value="Save Changes To Post"]')
3003
+ end
3004
+ end
3005
+ end
3006
+
3007
+ describe 'when used on a new record' do
3008
+
3009
+ it 'should render an input with a value attribute of "Create Post"' do
3010
+ @new_post.stub!(:new_record?).and_return(true)
3011
+ semantic_form_for(@new_post) do |builder|
3012
+ concat(builder.commit_button)
3013
+ end
3014
+ output_buffer.should have_tag('li.commit input[@value="Create Post"]')
3015
+ end
3016
+
3017
+ describe 'when the locale sets the label text' do
3018
+ before do
3019
+ I18n.backend.store_translations 'en', :formtastic => {:create => 'Make' }
3020
+ semantic_form_for(@new_post) do |builder|
3021
+ concat(builder.commit_button)
3022
+ end
3023
+ end
3024
+
3025
+ after do
3026
+ I18n.backend.store_translations 'en', :formtastic => {:create => nil}
3027
+ end
3028
+
3029
+ it 'should allow translation of the labels' do
3030
+ output_buffer.should have_tag('li.commit input[@value="Make Post"]')
3031
+ end
3032
+ end
3033
+
3034
+ end
3035
+
3036
+ describe 'when used without object' do
3037
+
3038
+ it 'should render an input with a value attribute of "Submit"' do
3039
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
3040
+ concat(builder.commit_button)
3041
+ end
3042
+
3043
+ output_buffer.should have_tag('li.commit input[@value="Submit Project"]')
3044
+ end
3045
+
3046
+ describe 'when the locale sets the label text' do
3047
+ before do
3048
+ I18n.backend.store_translations 'en', :formtastic => { :submit => 'Send' }
3049
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
3050
+ concat(builder.commit_button)
3051
+ end
3052
+ end
3053
+
3054
+ after do
3055
+ I18n.backend.store_translations 'en', :formtastic => {:submit => nil}
3056
+ end
3057
+
3058
+ it 'should allow translation of the labels' do
3059
+ output_buffer.should have_tag('li.commit input[@value="Send Project"]')
3060
+ end
3061
+ end
3062
+
3063
+ end
3064
+
3065
+ end
3066
+
3067
+ end
3068
+
3069
+ end