justinfrench-formtastic 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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