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