formtastic 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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