ui_datepicker-rails3 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ require 'base_helper'
2
+ require 'rails'
3
+
4
+ describe UiDatePickerRails3 do
5
+ describe 'activate' do
6
+ context 'formtastic' do
7
+ before do
8
+ require 'formtastic'
9
+ UiDatePickerRails3.activate :formtastic
10
+ end
11
+
12
+ specify { defined?(Formtastic::Inputs::UiDatePickerInput).should be_true }
13
+ specify { defined?(Formtastic::Inputs::UiDateTimePickerInput).should be_true }
14
+ end
15
+
16
+ context 'simple_form' do
17
+ before do
18
+ require 'simple_form'
19
+ UiDatePickerRails3.activate :simple_form
20
+ end
21
+
22
+ specify { defined?(SimpleForm::Inputs::UiDatePickerInput).should be_true }
23
+ specify { defined?(SimpleForm::Inputs::UiDateTimePickerInput).should be_true }
24
+ end
25
+
26
+ context 'active_admin' do
27
+ before do
28
+ require 'active_admin'
29
+ UiDatePickerRails3.activate :active_admin
30
+ end
31
+
32
+ specify { defined?(ActiveAdmin::Inputs::UiDatePickerInput).should be_true }
33
+ specify { defined?(ActiveAdmin::Inputs::UiDateTimePickerInput).should be_true }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,316 @@
1
+ # encoding: utf-8
2
+
3
+ require 'base_helper'
4
+
5
+ module FormtasticDatepickerInputsSpecHelper
6
+ include ActionPack
7
+ include ActionView::Context if defined?(ActionView::Context)
8
+ include ActionController::RecordIdentifier
9
+ include ActionView::Helpers::FormHelper
10
+ include ActionView::Helpers::FormTagHelper
11
+ include ActionView::Helpers::FormOptionsHelper
12
+ include ActionView::Helpers::UrlHelper
13
+ include ActionView::Helpers::TagHelper
14
+ include ActionView::Helpers::TextHelper
15
+ include ActionView::Helpers::ActiveRecordHelper if defined?(ActionView::Helpers::ActiveRecordHelper)
16
+ include ActionView::Helpers::ActiveModelHelper if defined?(ActionView::Helpers::ActiveModelHelper)
17
+ include ActionView::Helpers::DateHelper
18
+ include ActionView::Helpers::CaptureHelper
19
+ include ActionView::Helpers::AssetTagHelper
20
+ include ActiveSupport
21
+ include ActionController::PolymorphicRoutes if defined?(ActionController::PolymorphicRoutes)
22
+
23
+ include Formtastic::Helpers::FormHelper
24
+
25
+ def default_input_type(column_type, column_name = :generic_column_name)
26
+ @new_post.stub!(column_name)
27
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => column_type)) unless column_type.nil?
28
+
29
+ semantic_form_for(@new_post) do |builder|
30
+ @default_type = builder.send(:default_input_type, column_name)
31
+ end
32
+
33
+ return @default_type
34
+ end
35
+
36
+ def active_model_validator(kind, attributes, options = {})
37
+ validator = mock("ActiveModel::Validations::#{kind.to_s.titlecase}Validator", :attributes => attributes, :options => options)
38
+ validator.stub!(:kind).and_return(kind)
39
+ validator
40
+ end
41
+
42
+ def active_model_presence_validator(attributes, options = {})
43
+ active_model_validator(:presence, attributes, options)
44
+ end
45
+
46
+ def active_model_length_validator(attributes, options = {})
47
+ active_model_validator(:length, attributes, options)
48
+ end
49
+
50
+ def active_model_inclusion_validator(attributes, options = {})
51
+ active_model_validator(:inclusion, attributes, options)
52
+ end
53
+
54
+ class ::Post
55
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
56
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
57
+
58
+ def id
59
+ end
60
+
61
+ def persisted?
62
+ end
63
+ end
64
+ module ::Namespaced
65
+ class Post
66
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
67
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
68
+
69
+ def id
70
+ end
71
+
72
+ def persisted?
73
+ end
74
+ end
75
+ end
76
+ class ::Author
77
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
78
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
79
+
80
+ def to_label
81
+ end
82
+ end
83
+ class ::Continent
84
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
85
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
86
+ end
87
+ class ::PostModel
88
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
89
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
90
+ end
91
+
92
+ def _routes
93
+ url_helpers = mock('url_helpers')
94
+ url_helpers.stub!(:hash_for_posts_path).and_return({})
95
+ url_helpers.stub!(:hash_for_post_path).and_return({})
96
+ url_helpers.stub!(:hash_for_post_models_path).and_return({})
97
+ url_helpers.stub!(:hash_for_authors_path).and_return({})
98
+
99
+ mock('_routes',
100
+ :url_helpers => url_helpers,
101
+ :url_for => "/mock/path"
102
+ )
103
+ end
104
+
105
+ def controller
106
+ mock('controller', :controller_path= => '', :params => {})
107
+ end
108
+
109
+ def default_url_options
110
+ {}
111
+ end
112
+
113
+ def mock_everything
114
+
115
+ # Resource-oriented styles like form_for(@post) will expect a path method for the object,
116
+ # so we're defining some here.
117
+ def post_models_path; "/postmodels/1"; end
118
+
119
+ def post_path(o); "/posts/1"; end
120
+ def posts_path; "/posts"; end
121
+ def new_post_path; "/posts/new"; end
122
+
123
+ def author_path(o); "/authors/1"; end
124
+ def authors_path; "/authors"; end
125
+ def new_author_path; "/authors/new"; end
126
+
127
+ @fred = ::Author.new
128
+ @fred.stub!(:class).and_return(::Author)
129
+ @fred.stub!(:to_label).and_return('Fred Smith')
130
+ @fred.stub!(:login).and_return('fred_smith')
131
+ @fred.stub!(:id).and_return(37)
132
+ @fred.stub!(:new_record?).and_return(false)
133
+ @fred.stub!(:errors).and_return(mock('errors', :[] => nil))
134
+ @fred.stub!(:to_key).and_return(nil)
135
+ @fred.stub!(:persisted?).and_return(nil)
136
+
137
+ @bob = ::Author.new
138
+ @bob.stub!(:to_label).and_return('Bob Rock')
139
+ @bob.stub!(:login).and_return('bob')
140
+ @bob.stub!(:created_at)
141
+ @bob.stub!(:id).and_return(42)
142
+ @bob.stub!(:posts).and_return([])
143
+ @bob.stub!(:post_ids).and_return([])
144
+ @bob.stub!(:new_record?).and_return(false)
145
+ @bob.stub!(:errors).and_return(mock('errors', :[] => nil))
146
+ @bob.stub!(:to_key).and_return(nil)
147
+ @bob.stub!(:persisted?).and_return(nil)
148
+
149
+ @james = ::Author.new
150
+ @james.stub!(:to_label).and_return('James Shock')
151
+ @james.stub!(:login).and_return('james')
152
+ @james.stub!(:id).and_return(75)
153
+ @james.stub!(:posts).and_return([])
154
+ @james.stub!(:post_ids).and_return([])
155
+ @james.stub!(:new_record?).and_return(false)
156
+ @james.stub!(:errors).and_return(mock('errors', :[] => nil))
157
+ @james.stub!(:to_key).and_return(nil)
158
+ @james.stub!(:persisted?).and_return(nil)
159
+
160
+
161
+ ::Author.stub!(:find).and_return([@fred, @bob])
162
+ ::Author.stub!(:all).and_return([@fred, @bob])
163
+ ::Author.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
164
+ ::Author.stub!(:human_name).and_return('::Author')
165
+ ::Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
166
+ ::Author.stub!(:content_columns).and_return([mock('column', :name => 'login'), mock('column', :name => 'created_at')])
167
+ ::Author.stub!(:to_key).and_return(nil)
168
+ ::Author.stub!(:persisted?).and_return(nil)
169
+
170
+ # Sometimes we need a mock @post object and some Authors for belongs_to
171
+ @new_post = mock('post')
172
+ @new_post.stub!(:class).and_return(::Post)
173
+ @new_post.stub!(:id).and_return(nil)
174
+ @new_post.stub!(:new_record?).and_return(true)
175
+ @new_post.stub!(:errors).and_return(mock('errors', :[] => nil))
176
+ @new_post.stub!(:author).and_return(nil)
177
+ @new_post.stub!(:reviewer).and_return(nil)
178
+ @new_post.stub!(:main_post).and_return(nil)
179
+ @new_post.stub!(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
180
+ @new_post.stub!(:to_key).and_return(nil)
181
+ @new_post.stub!(:to_model).and_return(@new_post)
182
+ @new_post.stub!(:persisted?).and_return(nil)
183
+
184
+ @freds_post = mock('post')
185
+ @freds_post.stub!(:to_ary)
186
+ @freds_post.stub!(:class).and_return(::Post)
187
+ @freds_post.stub!(:to_label).and_return('Fred Smith')
188
+ @freds_post.stub!(:id).and_return(19)
189
+ @freds_post.stub!(:title).and_return("Hello World")
190
+ @freds_post.stub!(:author).and_return(@fred)
191
+ @freds_post.stub!(:author_id).and_return(@fred.id)
192
+ @freds_post.stub!(:authors).and_return([@fred])
193
+ @freds_post.stub!(:author_ids).and_return([@fred.id])
194
+ @freds_post.stub!(:new_record?).and_return(false)
195
+ @freds_post.stub!(:errors).and_return(mock('errors', :[] => nil))
196
+ @freds_post.stub!(:to_key).and_return(nil)
197
+ @freds_post.stub!(:persisted?).and_return(nil)
198
+ @fred.stub!(:posts).and_return([@freds_post])
199
+ @fred.stub!(:post_ids).and_return([@freds_post.id])
200
+
201
+ ::Post.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
202
+ ::Post.stub!(:human_name).and_return('Post')
203
+ ::Post.stub!(:reflect_on_all_validations).and_return([])
204
+ ::Post.stub!(:reflect_on_validations_for).and_return([])
205
+ ::Post.stub!(:reflections).and_return({})
206
+ ::Post.stub!(:reflect_on_association).and_return do |column_name|
207
+ case column_name
208
+ when :author, :author_status
209
+ mock = mock('reflection', :options => {}, :klass => ::Author, :macro => :belongs_to)
210
+ mock.stub!(:[]).with(:class_name).and_return("Author")
211
+ mock
212
+ when :reviewer
213
+ mock = mock('reflection', :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to)
214
+ mock.stub!(:[]).with(:class_name).and_return("Author")
215
+ mock
216
+ when :authors
217
+ mock('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
218
+ when :sub_posts
219
+ mock('reflection', :options => {}, :klass => ::Post, :macro => :has_many)
220
+ when :main_post
221
+ mock('reflection', :options => {}, :klass => ::Post, :macro => :belongs_to)
222
+ end
223
+
224
+ end
225
+ ::Post.stub!(:find).and_return([@freds_post])
226
+ ::Post.stub!(:all).and_return([@freds_post])
227
+ ::Post.stub!(:content_columns).and_return([mock('column', :name => 'title'), mock('column', :name => 'body'), mock('column', :name => 'created_at')])
228
+ ::Post.stub!(:to_key).and_return(nil)
229
+ ::Post.stub!(:persisted?).and_return(nil)
230
+ ::Post.stub!(:to_ary)
231
+
232
+ @mock_file = mock('file')
233
+ ::Formtastic::FormBuilder.file_methods.each do |method|
234
+ @mock_file.stub!(method).and_return(true)
235
+ end
236
+
237
+ @new_post.stub!(:title)
238
+ @new_post.stub!(:email)
239
+ @new_post.stub!(:url)
240
+ @new_post.stub!(:phone)
241
+ @new_post.stub!(:search)
242
+ @new_post.stub!(:to_ary)
243
+ @new_post.stub!(:body)
244
+ @new_post.stub!(:published)
245
+ @new_post.stub!(:publish_at)
246
+ @new_post.stub!(:created_at)
247
+ @new_post.stub!(:secret)
248
+ @new_post.stub!(:url)
249
+ @new_post.stub!(:email)
250
+ @new_post.stub!(:search)
251
+ @new_post.stub!(:phone)
252
+ @new_post.stub!(:time_zone)
253
+ @new_post.stub!(:category_name)
254
+ @new_post.stub!(:allow_comments).and_return(true)
255
+ @new_post.stub!(:answer_comments)
256
+ @new_post.stub!(:country)
257
+ @new_post.stub!(:country_subdivision)
258
+ @new_post.stub!(:country_code)
259
+ @new_post.stub!(:document).and_return(@mock_file)
260
+ @new_post.stub!(:column_for_attribute).with(:meta_description).and_return(mock('column', :type => :string, :limit => 255))
261
+ @new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 50))
262
+ @new_post.stub!(:column_for_attribute).with(:body).and_return(mock('column', :type => :text))
263
+ @new_post.stub!(:column_for_attribute).with(:published).and_return(mock('column', :type => :boolean))
264
+ @new_post.stub!(:column_for_attribute).with(:publish_at).and_return(mock('column', :type => :date, :limit => 255))
265
+ @new_post.stub!(:column_for_attribute).with(:time_zone).and_return(mock('column', :type => :string))
266
+ @new_post.stub!(:column_for_attribute).with(:allow_comments).and_return(mock('column', :type => :boolean))
267
+ @new_post.stub!(:column_for_attribute).with(:author).and_return(mock('column', :type => :integer))
268
+ @new_post.stub!(:column_for_attribute).with(:country).and_return(mock('column', :type => :string, :limit => 255))
269
+ @new_post.stub!(:column_for_attribute).with(:country_subdivision).and_return(mock('column', :type => :string, :limit => 255))
270
+ @new_post.stub!(:column_for_attribute).with(:country_code).and_return(mock('column', :type => :string, :limit => 255))
271
+ @new_post.stub!(:column_for_attribute).with(:email).and_return(mock('column', :type => :string, :limit => 255))
272
+ @new_post.stub!(:column_for_attribute).with(:url).and_return(mock('column', :type => :string, :limit => 255))
273
+ @new_post.stub!(:column_for_attribute).with(:phone).and_return(mock('column', :type => :string, :limit => 255))
274
+ @new_post.stub!(:column_for_attribute).with(:search).and_return(mock('column', :type => :string, :limit => 255))
275
+ @new_post.stub!(:column_for_attribute).with(:document).and_return(nil)
276
+
277
+ @new_post.stub!(:author).and_return(@bob)
278
+ @new_post.stub!(:author_id).and_return(@bob.id)
279
+
280
+ @new_post.stub!(:reviewer).and_return(@fred)
281
+ @new_post.stub!(:reviewer_id).and_return(@fred.id)
282
+
283
+ @new_post.should_receive(:publish_at=).any_number_of_times
284
+ @new_post.should_receive(:title=).any_number_of_times
285
+ @new_post.stub!(:main_post_id).and_return(nil)
286
+
287
+ end
288
+
289
+ def self.included(base)
290
+ base.class_eval do
291
+
292
+ attr_accessor :output_buffer
293
+
294
+ def protect_against_forgery?
295
+ false
296
+ end
297
+
298
+ end
299
+ end
300
+
301
+ def with_config(config_method_name, value, &block)
302
+ old_value = ::Formtastic::FormBuilder.send(config_method_name)
303
+ ::Formtastic::FormBuilder.send(:"#{config_method_name}=", value)
304
+ yield
305
+ ::Formtastic::FormBuilder.send(:"#{config_method_name}=", old_value)
306
+ end
307
+
308
+ def with_deprecation_silenced(&block)
309
+ ::ActiveSupport::Deprecation.silenced = true
310
+ yield
311
+ ::ActiveSupport::Deprecation.silenced = false
312
+ end
313
+
314
+ end
315
+
316
+ ::ActiveSupport::Deprecation.silenced = false
@@ -0,0 +1,520 @@
1
+ # encoding: utf-8
2
+
3
+ module CustomMacros
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def it_should_have_input_wrapper_with_class(class_name)
12
+ it "should have input wrapper with class '#{class_name}'" do
13
+ output_buffer.concat(@form)
14
+ output_buffer.should have_tag("form li.#{class_name}")
15
+ end
16
+ end
17
+
18
+ def it_should_have_input_wrapper_with_id(id_string)
19
+ it "should have input wrapper with id '#{id_string}'" do
20
+ output_buffer.concat(@form)
21
+ output_buffer.should have_tag("form li##{id_string}")
22
+ end
23
+ end
24
+
25
+ def it_should_not_have_a_label
26
+ it "should not have a label" do
27
+ output_buffer.concat(@form)
28
+ output_buffer.should_not have_tag("form li label")
29
+ end
30
+ end
31
+
32
+ def it_should_have_a_nested_fieldset
33
+ it "should have a nested_fieldset" do
34
+ output_buffer.concat(@form)
35
+ output_buffer.should have_tag("form li fieldset")
36
+ end
37
+ end
38
+
39
+ def it_should_have_label_with_text(string_or_regex)
40
+ it "should have a label with text '#{string_or_regex}'" do
41
+ output_buffer.concat(@form)
42
+ output_buffer.should have_tag("form li label", string_or_regex)
43
+ end
44
+ end
45
+
46
+ def it_should_have_label_for(element_id)
47
+ it "should have a label for ##{element_id}" do
48
+ output_buffer.concat(@form)
49
+ output_buffer.should have_tag("form li label[@for='#{element_id}']")
50
+ end
51
+ end
52
+
53
+ def it_should_have_input_with_id(element_id)
54
+ it "should have an input with id '#{element_id}'" do
55
+ output_buffer.concat(@form)
56
+ output_buffer.should have_tag("form li input##{element_id}")
57
+ end
58
+ end
59
+
60
+ def it_should_have_input_with_class(element_class)
61
+ it "should have an input with class '#{element_class}'" do
62
+ output_buffer.concat(@form)
63
+ output_buffer.should have_tag("form li input.#{element_class}")
64
+ end
65
+ end
66
+
67
+ def it_should_have_select_with_id(element_id)
68
+ it "should have a select box with id '#{element_id}'" do
69
+ output_buffer.concat(@form)
70
+ output_buffer.should have_tag("form li select##{element_id}")
71
+ end
72
+ end
73
+
74
+ def it_should_have_input_with_type(input_type)
75
+ it "should have a #{input_type} input" do
76
+ output_buffer.concat(@form)
77
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
78
+ end
79
+ end
80
+
81
+ def it_should_have_input_with_name(name)
82
+ it "should have an input named #{name}" do
83
+ output_buffer.concat(@form)
84
+ output_buffer.should have_tag("form li input[@name=\"#{name}\"]")
85
+ end
86
+ end
87
+
88
+ def it_should_have_textarea_with_name(name)
89
+ it "should have an input named #{name}" do
90
+ output_buffer.concat(@form)
91
+ output_buffer.should have_tag("form li textarea[@name=\"#{name}\"]")
92
+ end
93
+ end
94
+
95
+ def it_should_have_textarea_with_id(element_id)
96
+ it "should have an input with id '#{element_id}'" do
97
+ output_buffer.concat(@form)
98
+ output_buffer.should have_tag("form li textarea##{element_id}")
99
+ end
100
+ end
101
+
102
+ def it_should_have_label_and_input_with_id(element_id)
103
+ it "should have an input with id '#{element_id}'" do
104
+ output_buffer.concat(@form)
105
+ output_buffer.should have_tag("form li input##{element_id}")
106
+ output_buffer.should have_tag("form li label[@for='#{element_id}']")
107
+ end
108
+ end
109
+
110
+ def it_should_use_default_text_field_size_when_not_nil(as)
111
+ it 'should use default_text_field_size when not nil' do
112
+ with_config :default_text_field_size, 30 do
113
+ form = semantic_form_for(@new_post) do |builder|
114
+ concat(builder.input(:title, :as => as))
115
+ end
116
+ output_buffer.concat(form)
117
+ output_buffer.should have_tag("form li input[@size='#{Formtastic::SemanticFormBuilder.default_text_field_size}']")
118
+ end
119
+ end
120
+ end
121
+
122
+ def it_should_not_use_default_text_field_size_when_nil(as)
123
+ it 'should not use default_text_field_size when nil' do
124
+ with_config :default_text_field_size, nil do
125
+ form = semantic_form_for(@new_post) do |builder|
126
+ concat(builder.input(:title, :as => as))
127
+ end
128
+ output_buffer.concat(form)
129
+ output_buffer.should have_tag("form li input")
130
+ output_buffer.should_not have_tag("form li input[@size]")
131
+ end
132
+ end
133
+ end
134
+
135
+ def it_should_apply_custom_input_attributes_when_input_html_provided(as)
136
+ it 'it should apply custom input attributes when input_html provided' do
137
+ form = semantic_form_for(@new_post) do |builder|
138
+ concat(builder.input(:title, :as => as, :input_html => { :class => 'myclass' }))
139
+ end
140
+ output_buffer.concat(form)
141
+ output_buffer.should have_tag("form li input.myclass")
142
+ end
143
+ end
144
+
145
+ def it_should_apply_custom_for_to_label_when_input_html_id_provided(as)
146
+ it 'it should apply custom for to label when input_html :id provided' do
147
+ form = semantic_form_for(@new_post) do |builder|
148
+ concat(builder.input(:title, :as => as, :input_html => { :id => 'myid' }))
149
+ end
150
+ output_buffer.concat(form)
151
+ output_buffer.should have_tag('form li label[@for="myid"]')
152
+ end
153
+ end
154
+
155
+ def it_should_have_maxlength_matching_column_limit
156
+ it 'should have a maxlength matching column limit' do
157
+ @new_post.column_for_attribute(:title).limit.should == 50
158
+ output_buffer.concat(@form)
159
+ output_buffer.should have_tag("form li input[@maxlength='50']")
160
+ end
161
+ end
162
+
163
+ def it_should_use_column_size_for_columns_shorter_than_default_text_field_size(as)
164
+ it 'should use the column size for columns shorter than default_text_field_size' do
165
+ column_limit_shorted_than_default = 1
166
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => as, :limit => column_limit_shorted_than_default))
167
+
168
+ form = semantic_form_for(@new_post) do |builder|
169
+ concat(builder.input(:title, :as => as))
170
+ end
171
+
172
+ output_buffer.concat(form)
173
+ output_buffer.should have_tag("form li input[@size='#{column_limit_shorted_than_default}']")
174
+ end
175
+ end
176
+
177
+ def it_should_apply_error_logic_for_input_type(type)
178
+ describe 'when there are errors on the object for this method' do
179
+ before do
180
+ @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
181
+ @errors = mock('errors')
182
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
183
+ ::Formtastic::SemanticFormBuilder.file_metadata_suffixes.each do |suffix|
184
+ @errors.stub!(:[]).with("title_#{suffix}".to_sym).and_return(nil)
185
+ end
186
+ @new_post.stub!(:errors).and_return(@errors)
187
+ end
188
+
189
+ it 'should apply an errors class to the list item' do
190
+ form = semantic_form_for(@new_post) do |builder|
191
+ concat(builder.input(:title, :as => type))
192
+ end
193
+ output_buffer.concat(form)
194
+ output_buffer.should have_tag('form li.error')
195
+ end
196
+
197
+ it 'should not wrap the input with the Rails default error wrapping' do
198
+ form = semantic_form_for(@new_post) do |builder|
199
+ concat(builder.input(:title, :as => type))
200
+ end
201
+ output_buffer.concat(form)
202
+ output_buffer.should_not have_tag('div.fieldWithErrors')
203
+ end
204
+
205
+ it 'should render a paragraph for the errors' do
206
+ ::Formtastic::SemanticFormBuilder.inline_errors = :sentence
207
+ form = semantic_form_for(@new_post) do |builder|
208
+ concat(builder.input(:title, :as => type))
209
+ end
210
+ output_buffer.concat(form)
211
+ output_buffer.should have_tag('form li.error p.inline-errors')
212
+ end
213
+
214
+ it 'should not display an error list' do
215
+ ::Formtastic::SemanticFormBuilder.inline_errors = :list
216
+ form = semantic_form_for(@new_post) do |builder|
217
+ concat(builder.input(:title, :as => type))
218
+ end
219
+ output_buffer.concat(form)
220
+ output_buffer.should have_tag('form li.error ul.errors')
221
+ end
222
+ end
223
+
224
+ describe 'when there are no errors on the object for this method' do
225
+ before do
226
+ @form = semantic_form_for(@new_post) do |builder|
227
+ concat(builder.input(:title, :as => type))
228
+ end
229
+ end
230
+
231
+ it 'should not apply an errors class to the list item' do
232
+ output_buffer.concat(@form)
233
+ output_buffer.should_not have_tag('form li.error')
234
+ end
235
+
236
+ it 'should not render a paragraph for the errors' do
237
+ output_buffer.concat(@form)
238
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
239
+ end
240
+
241
+ it 'should not display an error list' do
242
+ output_buffer.concat(@form)
243
+ output_buffer.should_not have_tag('form li.error ul.errors')
244
+ end
245
+ end
246
+
247
+ describe 'when no object is provided' do
248
+ before do
249
+ @form = semantic_form_for(:project, :url => 'http://test.host') do |builder|
250
+ concat(builder.input(:title, :as => type))
251
+ end
252
+ end
253
+
254
+ it 'should not apply an errors class to the list item' do
255
+ output_buffer.concat(@form)
256
+ output_buffer.should_not have_tag('form li.error')
257
+ end
258
+
259
+ it 'should not render a paragraph for the errors' do
260
+ output_buffer.concat(@form)
261
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
262
+ end
263
+
264
+ it 'should not display an error list' do
265
+ output_buffer.concat(@form)
266
+ output_buffer.should_not have_tag('form li.error ul.errors')
267
+ end
268
+ end
269
+ end
270
+
271
+ def it_should_call_find_on_association_class_when_no_collection_is_provided(as)
272
+ it "should call find on the association class when no collection is provided" do
273
+ ::Author.should_receive(:all)
274
+ form = semantic_form_for(@new_post) do |builder|
275
+ concat(builder.input(:author, :as => as))
276
+ end
277
+ end
278
+ end
279
+
280
+ def it_should_use_the_collection_when_provided(as, countable)
281
+ describe 'when the :collection option is provided' do
282
+
283
+ before do
284
+ @authors = ::Author.all * 2
285
+ output_buffer.replace '' # clears the output_buffer from the before block, hax!
286
+ end
287
+
288
+ it 'should use the provided collection' do
289
+ form = semantic_form_for(@new_post) do |builder|
290
+ concat(builder.input(:author, :as => as, :collection => @authors))
291
+ end
292
+ output_buffer.concat(form)
293
+ output_buffer.should have_tag("form li.#{as} #{countable}", :count => @authors.size + (as == :select ? 1 : 0))
294
+ end
295
+
296
+ describe 'and the :collection is an array of strings' do
297
+ before do
298
+ @categories = [ 'General', 'Design', 'Development', 'Quasi-Serious Inventions' ]
299
+ end
300
+
301
+ it "should use the string as the label text and value for each #{countable}" do
302
+ form = semantic_form_for(@new_post) do |builder|
303
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
304
+ end
305
+ output_buffer.concat(form)
306
+
307
+ @categories.each do |value|
308
+ output_buffer.should have_tag("form li.#{as}", /#{value}/)
309
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
310
+ end
311
+ end
312
+
313
+ if as == :radio
314
+ it 'should generate a sanitized label for attribute' do
315
+ @bob.stub!(:category_name).and_return(@categories)
316
+ form = semantic_form_for(@new_post) do |builder|
317
+ fields = builder.semantic_fields_for(@bob) do |bob_builder|
318
+ concat(bob_builder.input(:category_name, :as => as, :collection => @categories))
319
+ end
320
+ concat(fields)
321
+ end
322
+ output_buffer.concat(form)
323
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_general']")
324
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_design']")
325
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_development']")
326
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_quasiserious_inventions']")
327
+ end
328
+ end
329
+ end
330
+
331
+ describe 'and the :collection is a hash of strings' do
332
+ before do
333
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }
334
+ end
335
+
336
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
337
+ form = semantic_form_for(@new_post) do |builder|
338
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
339
+ end
340
+ output_buffer.concat(form)
341
+
342
+ @categories.each do |label, value|
343
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
344
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
345
+ end
346
+ end
347
+ end
348
+
349
+ describe 'and the :collection is an array of arrays' do
350
+ before do
351
+ @categories = { 'General' => 'gen', 'Design' => 'des', 'Development' => 'dev' }.to_a
352
+ end
353
+
354
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
355
+ form = semantic_form_for(@new_post) do |builder|
356
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
357
+ end
358
+ output_buffer.concat(form)
359
+
360
+ @categories.each do |text, value|
361
+ label = as == :select ? :option : :label
362
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{text}/i)
363
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
364
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_#{value.to_s}") if as == :radio
365
+ end
366
+ end
367
+ end
368
+
369
+ if as == :radio
370
+ describe 'and the :collection is an array of arrays with boolean values' do
371
+ before do
372
+ @choices = { 'Yeah' => true, 'Nah' => false }.to_a
373
+ end
374
+
375
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
376
+ form = semantic_form_for(@new_post) do |builder|
377
+ concat(builder.input(:category_name, :as => as, :collection => @choices))
378
+ end
379
+ output_buffer.concat(form)
380
+
381
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_true")
382
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_false")
383
+ end
384
+ end
385
+ end
386
+
387
+ describe 'and the :collection is an array of symbols' do
388
+ before do
389
+ @categories = [ :General, :Design, :Development ]
390
+ end
391
+
392
+ it "should use the symbol as the label text and value for each #{countable}" do
393
+ form = semantic_form_for(@new_post) do |builder|
394
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
395
+ end
396
+ output_buffer.concat(form)
397
+
398
+ @categories.each do |value|
399
+ label = as == :select ? :option : :label
400
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{value}/i)
401
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
402
+ end
403
+ end
404
+ end
405
+
406
+ describe 'and the :collection is an OrderedHash of strings' do
407
+ before do
408
+ @categories = ActiveSupport::OrderedHash.new('General' => 'gen', 'Design' => 'des','Development' => 'dev')
409
+ end
410
+
411
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
412
+ form = semantic_form_for(@new_post) do |builder|
413
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
414
+ end
415
+ output_buffer.concat(form)
416
+
417
+ @categories.each do |label, value|
418
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
419
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
420
+ end
421
+ end
422
+
423
+ end
424
+
425
+ describe 'when the :label_method option is provided' do
426
+
427
+ describe 'as a symbol' do
428
+ before do
429
+ @form = semantic_form_for(@new_post) do |builder|
430
+ concat(builder.input(:author, :as => as, :label_method => :login))
431
+ end
432
+ end
433
+
434
+ it 'should have options with text content from the specified method' do
435
+ output_buffer.concat(@form)
436
+ ::Author.all.each do |author|
437
+ output_buffer.should have_tag("form li.#{as}", /#{author.login}/)
438
+ end
439
+ end
440
+ end
441
+
442
+ describe 'as a proc' do
443
+ before do
444
+ @form = semantic_form_for(@new_post) do |builder|
445
+ concat(builder.input(:author, :as => as, :label_method => Proc.new {|a| a.login.reverse }))
446
+ end
447
+ end
448
+
449
+ it 'should have options with the proc applied to each' do
450
+ output_buffer.concat(@form)
451
+ ::Author.all.each do |author|
452
+ output_buffer.should have_tag("form li.#{as}", /#{author.login.reverse}/)
453
+ end
454
+ end
455
+ end
456
+
457
+ end
458
+
459
+ describe 'when the :label_method option is not provided' do
460
+ ::Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
461
+
462
+ describe "when the collection objects respond to #{label_method}" do
463
+ before do
464
+ @fred.stub!(:respond_to?).and_return { |m| m.to_s == label_method || m.to_s == 'id' }
465
+ ::Author.all.each { |a| a.stub!(label_method).and_return('The Label Text') }
466
+
467
+ @form = semantic_form_for(@new_post) do |builder|
468
+ concat(builder.input(:author, :as => as))
469
+ end
470
+ end
471
+
472
+ it "should render the options with #{label_method} as the label" do
473
+ output_buffer.concat(@form)
474
+ ::Author.all.each do |author|
475
+ output_buffer.should have_tag("form li.#{as}", /The Label Text/)
476
+ end
477
+ end
478
+ end
479
+
480
+ end
481
+ end
482
+
483
+ describe 'when the :value_method option is provided' do
484
+
485
+ describe 'as a symbol' do
486
+ before do
487
+ @form = semantic_form_for(@new_post) do |builder|
488
+ concat(builder.input(:author, :as => as, :value_method => :login))
489
+ end
490
+ end
491
+
492
+ it 'should have options with values from specified method' do
493
+ output_buffer.concat(@form)
494
+ ::Author.all.each do |author|
495
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login}']")
496
+ end
497
+ end
498
+ end
499
+
500
+ describe 'as a proc' do
501
+ before do
502
+ @form = semantic_form_for(@new_post) do |builder|
503
+ concat(builder.input(:author, :as => as, :value_method => Proc.new {|a| a.login.reverse }))
504
+ end
505
+ end
506
+
507
+ it 'should have options with the proc applied to each value' do
508
+ output_buffer.concat(@form)
509
+ ::Author.all.each do |author|
510
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login.reverse}']")
511
+ end
512
+ end
513
+ end
514
+ end
515
+
516
+ end
517
+ end
518
+
519
+ end
520
+ end