formtastic 0.9.0 → 0.9.1

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