sensis-formtastic-rails3 1.d4e5326

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.textile +584 -0
  3. data/Rakefile +127 -0
  4. data/generators/form/USAGE +16 -0
  5. data/generators/form/form_generator.rb +120 -0
  6. data/generators/form/templates/view__form.html.erb +5 -0
  7. data/generators/form/templates/view__form.html.haml +4 -0
  8. data/generators/formtastic/formtastic_generator.rb +24 -0
  9. data/generators/formtastic/templates/formtastic.css +131 -0
  10. data/generators/formtastic/templates/formtastic.rb +54 -0
  11. data/generators/formtastic/templates/formtastic_changes.css +14 -0
  12. data/generators/formtastic_stylesheets/formtastic_stylesheets_generator.rb +16 -0
  13. data/init.rb +5 -0
  14. data/lib/formtastic.rb +1870 -0
  15. data/lib/formtastic/i18n.rb +35 -0
  16. data/lib/formtastic/layout_helper.rb +10 -0
  17. data/lib/formtastic/railtie.rb +12 -0
  18. data/lib/formtastic/util.rb +36 -0
  19. data/lib/generators/formtastic/form/form_generator.rb +86 -0
  20. data/lib/generators/formtastic/install/install_generator.rb +24 -0
  21. data/lib/locale/en.yml +8 -0
  22. data/rails/init.rb +2 -0
  23. data/spec/buttons_spec.rb +166 -0
  24. data/spec/commit_button_spec.rb +401 -0
  25. data/spec/custom_builder_spec.rb +98 -0
  26. data/spec/defaults_spec.rb +20 -0
  27. data/spec/error_proc_spec.rb +27 -0
  28. data/spec/errors_spec.rb +105 -0
  29. data/spec/form_helper_spec.rb +142 -0
  30. data/spec/helpers/layout_helper_spec.rb +21 -0
  31. data/spec/i18n_spec.rb +152 -0
  32. data/spec/include_blank_spec.rb +74 -0
  33. data/spec/input_spec.rb +786 -0
  34. data/spec/inputs/boolean_input_spec.rb +104 -0
  35. data/spec/inputs/check_boxes_input_spec.rb +426 -0
  36. data/spec/inputs/country_input_spec.rb +118 -0
  37. data/spec/inputs/date_input_spec.rb +168 -0
  38. data/spec/inputs/datetime_input_spec.rb +310 -0
  39. data/spec/inputs/file_input_spec.rb +34 -0
  40. data/spec/inputs/hidden_input_spec.rb +78 -0
  41. data/spec/inputs/numeric_input_spec.rb +44 -0
  42. data/spec/inputs/password_input_spec.rb +46 -0
  43. data/spec/inputs/radio_input_spec.rb +243 -0
  44. data/spec/inputs/select_input_spec.rb +546 -0
  45. data/spec/inputs/string_input_spec.rb +64 -0
  46. data/spec/inputs/text_input_spec.rb +34 -0
  47. data/spec/inputs/time_input_spec.rb +206 -0
  48. data/spec/inputs/time_zone_input_spec.rb +110 -0
  49. data/spec/inputs_spec.rb +476 -0
  50. data/spec/label_spec.rb +89 -0
  51. data/spec/semantic_errors_spec.rb +98 -0
  52. data/spec/semantic_fields_for_spec.rb +45 -0
  53. data/spec/spec.opts +2 -0
  54. data/spec/spec_helper.rb +289 -0
  55. data/spec/support/custom_macros.rb +494 -0
  56. data/spec/support/output_buffer.rb +4 -0
  57. data/spec/support/test_environment.rb +45 -0
  58. metadata +234 -0
@@ -0,0 +1,494 @@
1
+ module CustomMacros
2
+
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def it_should_have_input_wrapper_with_class(class_name)
10
+ it "should have input wrapper with class '#{class_name}'" do
11
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
12
+ output_buffer.should have_tag("form li.#{class_name}")
13
+ end
14
+ end
15
+
16
+ def it_should_have_input_wrapper_with_id(id_string)
17
+ it "should have input wrapper with id '#{id_string}'" do
18
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
19
+ output_buffer.should have_tag("form li##{id_string}")
20
+ end
21
+ end
22
+
23
+ def it_should_not_have_a_label
24
+ it "should not have a label" do
25
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
26
+ output_buffer.should_not have_tag("form li label")
27
+ end
28
+ end
29
+
30
+ def it_should_have_a_nested_fieldset
31
+ it "should have a nested_fieldset" do
32
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
33
+ output_buffer.should have_tag("form li fieldset")
34
+ end
35
+ end
36
+
37
+ def it_should_have_label_with_text(string_or_regex)
38
+ it "should have a label with text '#{string_or_regex}'" do
39
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
40
+ output_buffer.should have_tag("form li label", string_or_regex)
41
+ end
42
+ end
43
+
44
+ def it_should_have_label_for(element_id)
45
+ it "should have a label for ##{element_id}" do
46
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
47
+ output_buffer.should have_tag("form li label[@for='#{element_id}']")
48
+ end
49
+ end
50
+
51
+ def it_should_have_input_with_id(element_id)
52
+ it "should have an input with id '#{element_id}'" do
53
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
54
+ output_buffer.should have_tag("form li input##{element_id}")
55
+ end
56
+ end
57
+
58
+ def it_should_have_input_with_type(input_type)
59
+ it "should have a #{input_type} input" do
60
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
61
+ output_buffer.should have_tag("form li input[@type=\"#{input_type}\"]")
62
+ end
63
+ end
64
+
65
+ def it_should_have_input_with_name(name)
66
+ it "should have an input named #{name}" do
67
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
68
+ output_buffer.should have_tag("form li input[@name=\"#{name}\"]")
69
+ end
70
+ end
71
+
72
+ def it_should_have_textarea_with_name(name)
73
+ it "should have an input named #{name}" do
74
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
75
+ output_buffer.should have_tag("form li textarea[@name=\"#{name}\"]")
76
+ end
77
+ end
78
+
79
+ def it_should_have_textarea_with_id(element_id)
80
+ it "should have an input with id '#{element_id}'" do
81
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
82
+ output_buffer.should have_tag("form li textarea##{element_id}")
83
+ end
84
+ end
85
+
86
+ def it_should_use_default_text_field_size_when_method_has_no_database_column(as)
87
+ it 'should use default_text_field_size when method has no database column' do
88
+ @new_post.stub!(:column_for_attribute).and_return(nil) # Return a nil column
89
+
90
+ form = semantic_form_for(@new_post) do |builder|
91
+ concat(builder.input(:title, :as => as))
92
+ end
93
+ output_buffer.concat(form) if Formtastic::Util.rails3?
94
+ output_buffer.should have_tag("form li input[@size='#{Formtastic::SemanticFormBuilder.default_text_field_size}']")
95
+ end
96
+ end
97
+
98
+ def it_should_apply_custom_input_attributes_when_input_html_provided(as)
99
+ it 'it should apply custom input attributes when input_html provided' do
100
+ form = semantic_form_for(@new_post) do |builder|
101
+ concat(builder.input(:title, :as => as, :input_html => { :class => 'myclass' }))
102
+ end
103
+ output_buffer.concat(form) if Formtastic::Util.rails3?
104
+ output_buffer.should have_tag("form li input.myclass")
105
+ end
106
+ end
107
+
108
+ def it_should_apply_custom_for_to_label_when_input_html_id_provided(as)
109
+ it 'it should apply custom for to label when input_html :id provided' do
110
+ form = semantic_form_for(@new_post) do |builder|
111
+ concat(builder.input(:title, :as => as, :input_html => { :id => 'myid' }))
112
+ end
113
+ output_buffer.concat(form) if Formtastic::Util.rails3?
114
+ output_buffer.should have_tag('form li label[@for="myid"]')
115
+ end
116
+ end
117
+
118
+ def it_should_have_maxlength_matching_column_limit
119
+ it 'should have a maxlength matching column limit' do
120
+ @new_post.column_for_attribute(:title).limit.should == 50
121
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
122
+ output_buffer.should have_tag("form li input[@maxlength='50']")
123
+ end
124
+ end
125
+
126
+ def it_should_use_default_text_field_size_for_columns_longer_than_default_text_field_size(as)
127
+ it 'should use default_text_field_size for columns longer than default_text_field_size' do
128
+ default_size = Formtastic::SemanticFormBuilder.default_text_field_size
129
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => as, :limit => default_size * 2))
130
+
131
+ form = semantic_form_for(@new_post) do |builder|
132
+ concat(builder.input(:title, :as => as))
133
+ end
134
+
135
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
136
+ output_buffer.should have_tag("form li input[@size='#{default_size}']")
137
+ end
138
+ end
139
+
140
+ def it_should_use_column_size_for_columns_shorter_than_default_text_field_size(as)
141
+ it 'should use the column size for columns shorter than default_text_field_size' do
142
+ column_limit_shorted_than_default = 1
143
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => as, :limit => column_limit_shorted_than_default))
144
+
145
+ form = semantic_form_for(@new_post) do |builder|
146
+ concat(builder.input(:title, :as => as))
147
+ end
148
+
149
+ output_buffer.concat(form) if Formtastic::Util.rails3?
150
+ output_buffer.should have_tag("form li input[@size='#{column_limit_shorted_than_default}']")
151
+ end
152
+ end
153
+
154
+ def it_should_apply_error_logic_for_input_type(type)
155
+ describe 'when there are errors on the object for this method' do
156
+ before do
157
+ @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
158
+ @errors = mock('errors')
159
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
160
+ @new_post.stub!(:errors).and_return(@errors)
161
+ end
162
+
163
+ it 'should apply an errors class to the list item' do
164
+ form = semantic_form_for(@new_post) do |builder|
165
+ concat(builder.input(:title, :as => type))
166
+ end
167
+ output_buffer.concat(form) if Formtastic::Util.rails3?
168
+ output_buffer.should have_tag('form li.error')
169
+ end
170
+
171
+ it 'should not wrap the input with the Rails default error wrapping' do
172
+ form = semantic_form_for(@new_post) do |builder|
173
+ concat(builder.input(:title, :as => type))
174
+ end
175
+ output_buffer.concat(form) if Formtastic::Util.rails3?
176
+ output_buffer.should_not have_tag('div.fieldWithErrors')
177
+ end
178
+
179
+ it 'should render a paragraph for the errors' do
180
+ ::Formtastic::SemanticFormBuilder.inline_errors = :sentence
181
+ form = semantic_form_for(@new_post) do |builder|
182
+ concat(builder.input(:title, :as => type))
183
+ end
184
+ output_buffer.concat(form) if Formtastic::Util.rails3?
185
+ output_buffer.should have_tag('form li.error p.inline-errors')
186
+ end
187
+
188
+ it 'should not display an error list' do
189
+ ::Formtastic::SemanticFormBuilder.inline_errors = :list
190
+ form = semantic_form_for(@new_post) do |builder|
191
+ concat(builder.input(:title, :as => type))
192
+ end
193
+ output_buffer.concat(form) if Formtastic::Util.rails3?
194
+ output_buffer.should have_tag('form li.error ul.errors')
195
+ end
196
+ end
197
+
198
+ describe 'when there are no errors on the object for this method' do
199
+ before do
200
+ @form = semantic_form_for(@new_post) do |builder|
201
+ concat(builder.input(:title, :as => type))
202
+ end
203
+ end
204
+
205
+ it 'should not apply an errors class to the list item' do
206
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
207
+ output_buffer.should_not have_tag('form li.error')
208
+ end
209
+
210
+ it 'should not render a paragraph for the errors' do
211
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
212
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
213
+ end
214
+
215
+ it 'should not display an error list' do
216
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
217
+ output_buffer.should_not have_tag('form li.error ul.errors')
218
+ end
219
+ end
220
+
221
+ describe 'when no object is provided' do
222
+ before do
223
+ @form = semantic_form_for(:project, :url => 'http://test.host') do |builder|
224
+ concat(builder.input(:title, :as => type))
225
+ end
226
+ end
227
+
228
+ it 'should not apply an errors class to the list item' do
229
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
230
+ output_buffer.should_not have_tag('form li.error')
231
+ end
232
+
233
+ it 'should not render a paragraph for the errors' do
234
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
235
+ output_buffer.should_not have_tag('form li.error p.inline-errors')
236
+ end
237
+
238
+ it 'should not display an error list' do
239
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
240
+ output_buffer.should_not have_tag('form li.error ul.errors')
241
+ end
242
+ end
243
+ end
244
+
245
+ def it_should_call_find_on_association_class_when_no_collection_is_provided(as)
246
+ it "should call find on the association class when no collection is provided" do
247
+ ::Author.should_receive(:all)
248
+ form = semantic_form_for(@new_post) do |builder|
249
+ concat(builder.input(:author, :as => as))
250
+ end
251
+ end
252
+ end
253
+
254
+ def it_should_use_the_collection_when_provided(as, countable)
255
+ describe 'when the :collection option is provided' do
256
+
257
+ before do
258
+ @authors = ::Author.find(:all) * 2
259
+ output_buffer.replace '' # clears the output_buffer from the before block, hax!
260
+ end
261
+
262
+ it 'should use the provided collection' do
263
+ form = semantic_form_for(@new_post) do |builder|
264
+ concat(builder.input(:author, :as => as, :collection => @authors))
265
+ end
266
+ output_buffer.concat(form) if Formtastic::Util.rails3?
267
+ output_buffer.should have_tag("form li.#{as} #{countable}", :count => @authors.size + (as == :select ? 1 : 0))
268
+ end
269
+
270
+ describe 'and the :collection is an array of strings' do
271
+ before do
272
+ @categories = [ 'General', 'Design', 'Development', 'Quasi-Serious Inventions' ]
273
+ end
274
+
275
+ it "should use the string as the label text and value for each #{countable}" do
276
+ form = semantic_form_for(@new_post) do |builder|
277
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
278
+ end
279
+ output_buffer.concat(form) if Formtastic::Util.rails3?
280
+
281
+ @categories.each do |value|
282
+ output_buffer.should have_tag("form li.#{as}", /#{value}/)
283
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
284
+ end
285
+ end
286
+
287
+ if as == :radio
288
+ it 'should generate a sanitized label for attribute' do
289
+ @bob.stub!(:category_name).and_return(@categories)
290
+ form = semantic_form_for(@new_post) do |builder|
291
+ fields = builder.semantic_fields_for(@bob) do |bob_builder|
292
+ concat(bob_builder.input(:category_name, :as => as, :collection => @categories))
293
+ end
294
+ concat(fields)
295
+ end
296
+ output_buffer.concat(form) if Formtastic::Util.rails3?
297
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_general']")
298
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_design']")
299
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_development']")
300
+ output_buffer.should have_tag("form li fieldset ol li label[@for='post_author_category_name_quasiserious_inventions']")
301
+ end
302
+ end
303
+ end
304
+
305
+ describe 'and the :collection is a hash of strings' do
306
+ before do
307
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }
308
+ end
309
+
310
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
311
+ form = semantic_form_for(@new_post) do |builder|
312
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
313
+ end
314
+ output_buffer.concat(form) if Formtastic::Util.rails3?
315
+
316
+ @categories.each do |label, value|
317
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
318
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
319
+ end
320
+ end
321
+ end
322
+
323
+ describe 'and the :collection is an array of arrays' do
324
+ before do
325
+ @categories = { 'General' => 'gen', 'Design' => 'des', 'Development' => 'dev' }.to_a
326
+ end
327
+
328
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
329
+ form = semantic_form_for(@new_post) do |builder|
330
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
331
+ end
332
+ output_buffer.concat(form) if Formtastic::Util.rails3?
333
+
334
+ @categories.each do |text, value|
335
+ label = as == :select ? :option : :label
336
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{text}/i)
337
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
338
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_#{value.to_s}") if as == :radio
339
+ end
340
+ end
341
+ end
342
+
343
+ if as == :radio
344
+ describe 'and the :collection is an array of arrays with boolean values' do
345
+ before do
346
+ @choices = { 'Yeah' => true, 'Nah' => false }.to_a
347
+ end
348
+
349
+ it "should use the first value as the label text and the last value as the value attribute for #{countable}" do
350
+ form = semantic_form_for(@new_post) do |builder|
351
+ concat(builder.input(:category_name, :as => as, :collection => @choices))
352
+ end
353
+ output_buffer.concat(form) if Formtastic::Util.rails3?
354
+
355
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_true")
356
+ output_buffer.should have_tag("form li.#{as} #{countable}#post_category_name_false")
357
+ end
358
+ end
359
+ end
360
+
361
+ describe 'and the :collection is an array of symbols' do
362
+ before do
363
+ @categories = [ :General, :Design, :Development ]
364
+ end
365
+
366
+ it "should use the symbol as the label text and value for each #{countable}" do
367
+ form = semantic_form_for(@new_post) do |builder|
368
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
369
+ end
370
+ output_buffer.concat(form) if Formtastic::Util.rails3?
371
+
372
+ @categories.each do |value|
373
+ label = as == :select ? :option : :label
374
+ output_buffer.should have_tag("form li.#{as} #{label}", /#{value}/i)
375
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value.to_s}']")
376
+ end
377
+ end
378
+ end
379
+
380
+ describe 'and the :collection is an OrderedHash of strings' do
381
+ before do
382
+ @categories = ActiveSupport::OrderedHash.new('General' => 'gen', 'Design' => 'des','Development' => 'dev')
383
+ end
384
+
385
+ it "should use the key as the label text and the hash value as the value attribute for each #{countable}" do
386
+ form = semantic_form_for(@new_post) do |builder|
387
+ concat(builder.input(:category_name, :as => as, :collection => @categories))
388
+ end
389
+ output_buffer.concat(form) if Formtastic::Util.rails3?
390
+
391
+ @categories.each do |label, value|
392
+ output_buffer.should have_tag("form li.#{as}", /#{label}/)
393
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{value}']")
394
+ end
395
+ end
396
+
397
+ end
398
+
399
+ describe 'when the :label_method option is provided' do
400
+
401
+ describe 'as a symbol' do
402
+ before do
403
+ @form = semantic_form_for(@new_post) do |builder|
404
+ concat(builder.input(:author, :as => as, :label_method => :login))
405
+ end
406
+ end
407
+
408
+ it 'should have options with text content from the specified method' do
409
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
410
+ ::Author.find(:all).each do |author|
411
+ output_buffer.should have_tag("form li.#{as}", /#{author.login}/)
412
+ end
413
+ end
414
+ end
415
+
416
+ describe 'as a proc' do
417
+ before do
418
+ @form = semantic_form_for(@new_post) do |builder|
419
+ concat(builder.input(:author, :as => as, :label_method => Proc.new {|a| a.login.reverse }))
420
+ end
421
+ end
422
+
423
+ it 'should have options with the proc applied to each' do
424
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
425
+ ::Author.find(:all).each do |author|
426
+ output_buffer.should have_tag("form li.#{as}", /#{author.login.reverse}/)
427
+ end
428
+ end
429
+ end
430
+
431
+ end
432
+
433
+ describe 'when the :label_method option is not provided' do
434
+ ::Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
435
+
436
+ describe "when the collection objects respond to #{label_method}" do
437
+ before do
438
+ @fred.stub!(:respond_to?).and_return { |m| m.to_s == label_method || m.to_s == 'id' }
439
+ ::Author.find(:all).each { |a| a.stub!(label_method).and_return('The Label Text') }
440
+
441
+ @form = semantic_form_for(@new_post) do |builder|
442
+ concat(builder.input(:author, :as => as))
443
+ end
444
+ end
445
+
446
+ it "should render the options with #{label_method} as the label" do
447
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
448
+ ::Author.find(:all).each do |author|
449
+ output_buffer.should have_tag("form li.#{as}", /The Label Text/)
450
+ end
451
+ end
452
+ end
453
+
454
+ end
455
+ end
456
+
457
+ describe 'when the :value_method option is provided' do
458
+
459
+ describe 'as a symbol' do
460
+ before do
461
+ @form = semantic_form_for(@new_post) do |builder|
462
+ concat(builder.input(:author, :as => as, :value_method => :login))
463
+ end
464
+ end
465
+
466
+ it 'should have options with values from specified method' do
467
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
468
+ ::Author.find(:all).each do |author|
469
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login}']")
470
+ end
471
+ end
472
+ end
473
+
474
+ describe 'as a proc' do
475
+ before do
476
+ @form = semantic_form_for(@new_post) do |builder|
477
+ concat(builder.input(:author, :as => as, :value_method => Proc.new {|a| a.login.reverse }))
478
+ end
479
+ end
480
+
481
+ it 'should have options with the proc applied to each value' do
482
+ output_buffer.concat(@form) if Formtastic::Util.rails3?
483
+ ::Author.find(:all).each do |author|
484
+ output_buffer.should have_tag("form li.#{as} #{countable}[@value='#{author.login.reverse}']")
485
+ end
486
+ end
487
+ end
488
+ end
489
+
490
+ end
491
+ end
492
+
493
+ end
494
+ end