justinfrench-formtastic 0.1.1

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