ui_datepicker-rails3 1.0.0

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.
@@ -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