lperichon-jintastic 1.0.1

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