ShadowBelmolve-formtastic 0.2.1 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/README.textile +191 -176
  2. data/Rakefile +65 -22
  3. data/generators/form/USAGE +16 -0
  4. data/generators/form/form_generator.rb +120 -0
  5. data/generators/form/templates/view__form.html.erb +5 -0
  6. data/generators/form/templates/view__form.html.haml +4 -0
  7. data/generators/formtastic/formtastic_generator.rb +24 -0
  8. data/generators/{formtastic_stylesheets → formtastic}/templates/formtastic.css +2 -0
  9. data/generators/formtastic/templates/formtastic.rb +51 -0
  10. data/generators/{formtastic_stylesheets → formtastic}/templates/formtastic_changes.css +0 -0
  11. data/generators/formtastic_stylesheets/formtastic_stylesheets_generator.rb +5 -10
  12. data/lib/formtastic.rb +1234 -895
  13. data/lib/formtastic/i18n.rb +32 -0
  14. data/lib/locale/en.yml +2 -2
  15. data/rails/init.rb +1 -1
  16. data/spec/buttons_spec.rb +149 -0
  17. data/spec/commit_button_spec.rb +344 -0
  18. data/spec/custom_builder_spec.rb +62 -0
  19. data/spec/custom_macros.rb +561 -0
  20. data/spec/defaults_spec.rb +20 -0
  21. data/spec/error_proc_spec.rb +27 -0
  22. data/spec/errors_spec.rb +85 -0
  23. data/spec/form_helper_spec.rb +120 -0
  24. data/spec/i18n_spec.rb +131 -0
  25. data/spec/include_blank_spec.rb +70 -0
  26. data/spec/input_spec.rb +608 -0
  27. data/spec/inputs/boolean_input_spec.rb +93 -0
  28. data/spec/inputs/check_boxes_input_spec.rb +162 -0
  29. data/spec/inputs/country_input_spec.rb +80 -0
  30. data/spec/inputs/date_input_spec.rb +45 -0
  31. data/spec/inputs/datetime_input_spec.rb +155 -0
  32. data/spec/inputs/file_input_spec.rb +33 -0
  33. data/spec/inputs/hidden_input_spec.rb +52 -0
  34. data/spec/inputs/numeric_input_spec.rb +44 -0
  35. data/spec/inputs/password_input_spec.rb +46 -0
  36. data/spec/inputs/radio_input_spec.rb +149 -0
  37. data/spec/inputs/select_input_spec.rb +459 -0
  38. data/spec/inputs/string_input_spec.rb +47 -0
  39. data/spec/inputs/text_input_spec.rb +33 -0
  40. data/spec/inputs/time_input_spec.rb +44 -0
  41. data/spec/inputs/time_zone_input_spec.rb +102 -0
  42. data/spec/inputs_spec.rb +395 -0
  43. data/spec/label_spec.rb +48 -0
  44. data/spec/nested_forms_spec.rb +50 -0
  45. data/spec/semantic_fields_for_spec.rb +44 -0
  46. data/spec/spec.opts +2 -0
  47. data/spec/spec_helper.rb +212 -0
  48. metadata +121 -16
  49. data/lib/justin_french/formtastic.rb +0 -10
  50. data/spec/formtastic_spec.rb +0 -3072
  51. data/spec/test_helper.rb +0 -14
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+ require File.join(File.dirname(__FILE__), *%w[spec_helper])
3
+
4
+ describe 'Formtastic::SemanticFormBuilder-defaults' do
5
+
6
+ # Note: This spec might make better sense somewhere else. Just temporary.
7
+
8
+ describe "required string" do
9
+
10
+ it "should render proc with I18n correctly" do
11
+ ::I18n.backend.store_translations :en, :formtastic => {:required => 'Haha!'}
12
+
13
+ required_string = Formtastic::SemanticFormBuilder.required_string
14
+ required_string = required_string.is_a?(::Proc) ? required_string.call : required_string.to_s
15
+ required_string.should == %{<abbr title="Haha!">*</abbr>}
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe 'Rails field_error_proc' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ it "should not be overridden globally for all form builders" do
14
+ current_field_error_proc = ::ActionView::Base.field_error_proc
15
+
16
+ semantic_form_for(@new_post) do |builder|
17
+ ::ActionView::Base.field_error_proc.should_not == current_field_error_proc
18
+ end
19
+
20
+ ::ActionView::Base.field_error_proc.should == current_field_error_proc
21
+
22
+ form_for(@new_post) do |builder|
23
+ ::ActionView::Base.field_error_proc.should == current_field_error_proc
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,85 @@
1
+ # coding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe 'SemanticFormBuilder#errors_on' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ @title_errors = ['must not be blank', 'must be longer than 10 characters', 'must be awesome']
12
+ @errors = mock('errors')
13
+ @new_post.stub!(:errors).and_return(@errors)
14
+ end
15
+
16
+ describe 'when there are errors' do
17
+ before do
18
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
19
+ end
20
+
21
+ it 'should render a paragraph with the errors joined into a sentence when inline_errors config is :sentence' do
22
+ ::Formtastic::SemanticFormBuilder.inline_errors = :sentence
23
+ semantic_form_for(@new_post) do |builder|
24
+ builder.errors_on(:title).should have_tag('p.inline-errors', @title_errors.to_sentence)
25
+ end
26
+ end
27
+
28
+ it 'should render an unordered list with the class errors when inline_errors config is :list' do
29
+ ::Formtastic::SemanticFormBuilder.inline_errors = :list
30
+ semantic_form_for(@new_post) do |builder|
31
+ builder.errors_on(:title).should have_tag('ul.errors')
32
+ @title_errors.each do |error|
33
+ builder.errors_on(:title).should have_tag('ul.errors li', error)
34
+ end
35
+ end
36
+ end
37
+
38
+ it 'should render a paragraph with the first error when inline_errors config is :first' do
39
+ ::Formtastic::SemanticFormBuilder.inline_errors = :first
40
+ semantic_form_for(@new_post) do |builder|
41
+ builder.errors_on(:title).should have_tag('p.inline-errors', @title_errors.first)
42
+ end
43
+ end
44
+
45
+ it 'should return nil when inline_errors config is :none' do
46
+ ::Formtastic::SemanticFormBuilder.inline_errors = :none
47
+ semantic_form_for(@new_post) do |builder|
48
+ builder.errors_on(:title).should be_nil
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ describe 'when there are no errors (nil)' do
55
+ before do
56
+ @errors.stub!(:[]).with(:title).and_return(nil)
57
+ end
58
+
59
+ it 'should return nil when inline_errors config is :sentence, :list or :none' do
60
+ [:sentence, :list, :none].each do |config|
61
+ ::Formtastic::SemanticFormBuilder.inline_errors = config
62
+ semantic_form_for(@new_post) do |builder|
63
+ builder.errors_on(:title).should be_nil
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ describe 'when there are no errors (empty array)' do
70
+ before do
71
+ @errors.stub!(:[]).with(:title).and_return([])
72
+ end
73
+
74
+ it 'should return nil when inline_errors config is :sentence, :list or :none' do
75
+ [:sentence, :list, :none].each do |config|
76
+ ::Formtastic::SemanticFormBuilder.inline_errors = config
77
+ semantic_form_for(@new_post) do |builder|
78
+ builder.errors_on(:title).should be_nil
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+
@@ -0,0 +1,120 @@
1
+ # coding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe 'SemanticFormHelper' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ describe '#semantic_form_for' do
14
+
15
+ it 'yields an instance of SemanticFormBuilder' do
16
+ semantic_form_for(:post, ::Post.new, :url => '/hello') do |builder|
17
+ builder.class.should == ::Formtastic::SemanticFormBuilder
18
+ end
19
+ end
20
+
21
+ it 'adds a class of "formtastic" to the generated form' do
22
+ semantic_form_for(:post, ::Post.new, :url => '/hello') do |builder|
23
+ end
24
+ output_buffer.should have_tag("form.formtastic")
25
+ end
26
+
27
+ it 'adds class matching the object name to the generated form when a symbol is provided' do
28
+ semantic_form_for(:post, ::Post.new, :url => '/hello') do |builder|
29
+ end
30
+ output_buffer.should have_tag("form.post")
31
+
32
+ semantic_form_for(:project, :url => '/hello') do |builder|
33
+ end
34
+ output_buffer.should have_tag("form.project")
35
+ end
36
+
37
+ it 'adds class matching the object\'s class to the generated form when an object is provided' do
38
+ semantic_form_for(@new_post) do |builder|
39
+ end
40
+ output_buffer.should have_tag("form.post")
41
+ end
42
+
43
+ describe 'allows :html options' do
44
+ before(:each) do
45
+ semantic_form_for(:post, ::Post.new, :url => '/hello', :html => { :id => "something-special", :class => "something-extra", :multipart => true }) do |builder|
46
+ end
47
+ end
48
+
49
+ it 'to add a id of "something-special" to generated form' do
50
+ output_buffer.should have_tag("form#something-special")
51
+ end
52
+
53
+ it 'to add a class of "something-extra" to generated form' do
54
+ output_buffer.should have_tag("form.something-extra")
55
+ end
56
+
57
+ it 'to add enctype="multipart/form-data"' do
58
+ output_buffer.should have_tag('form[@enctype="multipart/form-data"]')
59
+ end
60
+ end
61
+
62
+ it 'can be called with a resource-oriented style' do
63
+ semantic_form_for(@new_post) do |builder|
64
+ builder.object.class.should == ::Post
65
+ builder.object_name.should == "post"
66
+ end
67
+ end
68
+
69
+ it 'can be called with a generic style and instance variable' do
70
+ semantic_form_for(:post, @new_post, :url => new_post_path) do |builder|
71
+ builder.object.class.should == ::Post
72
+ builder.object_name.to_s.should == "post" # TODO: is this forced .to_s a bad assumption somewhere?
73
+ end
74
+ end
75
+
76
+ it 'can be called with a generic style and inline object' do
77
+ semantic_form_for(:post, ::Post.new, :url => new_post_path) do |builder|
78
+ builder.object.class.should == ::Post
79
+ builder.object_name.to_s.should == "post" # TODO: is this forced .to_s a bad assumption somewhere?
80
+ end
81
+ end
82
+
83
+ describe "with :builder option" do
84
+ it "yields an instance of the given builder" do
85
+ class MyAwesomeCustomBuilder < ::Formtastic::SemanticFormBuilder
86
+ end
87
+ semantic_form_for(:post, ::Post.new, :url => '/hello', :builder => MyAwesomeCustomBuilder) do |builder|
88
+ builder.class.should == MyAwesomeCustomBuilder
89
+ end
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ describe '#semantic_fields_for' do
96
+ it 'yields an instance of SemanticFormBuilder' do
97
+ semantic_fields_for(:post, ::Post.new, :url => '/hello') do |builder|
98
+ builder.class.should == ::Formtastic::SemanticFormBuilder
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '#semantic_form_remote_for' do
104
+ it 'yields an instance of SemanticFormBuilder' do
105
+ semantic_form_remote_for(:post, ::Post.new, :url => '/hello') do |builder|
106
+ builder.class.should == ::Formtastic::SemanticFormBuilder
107
+ end
108
+ end
109
+ end
110
+
111
+ describe '#semantic_form_for_remote' do
112
+ it 'yields an instance of SemanticFormBuilder' do
113
+ semantic_remote_form_for(:post, ::Post.new, :url => '/hello') do |builder|
114
+ builder.class.should == ::Formtastic::SemanticFormBuilder
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+
@@ -0,0 +1,131 @@
1
+ # coding: utf-8
2
+ require File.join(File.dirname(__FILE__), *%w[spec_helper])
3
+
4
+ describe 'Formtastic::I18n' do
5
+
6
+ FORMTASTIC_KEYS = [:required, :yes, :no, :create, :update].freeze
7
+
8
+ it "should be defined" do
9
+ lambda { ::Formtastic::I18n }.should_not raise_error(::NameError)
10
+ end
11
+
12
+ describe "default translations" do
13
+ it "should be defined" do
14
+ lambda { ::Formtastic::I18n::DEFAULT_VALUES }.should_not raise_error(::NameError)
15
+ ::Formtastic::I18n::DEFAULT_VALUES.is_a?(::Hash).should == true
16
+ end
17
+
18
+ it "should exists for the core I18n lookup keys" do
19
+ (::Formtastic::I18n::DEFAULT_VALUES.keys & FORMTASTIC_KEYS).size.should == FORMTASTIC_KEYS.size
20
+ end
21
+ end
22
+
23
+ describe "when I18n locales are available" do
24
+
25
+ before do
26
+ @formtastic_strings = {
27
+ :required => 'Default Required',
28
+ :yes => 'Default Yes',
29
+ :no => 'Default No',
30
+ :create => 'Default Create {{model}}',
31
+ :update => 'Default Update {{model}}',
32
+ :custom_scope => {
33
+ :duck => 'Duck',
34
+ :duck_pond => '{{ducks}} ducks in a pond'
35
+ }
36
+ }
37
+ ::I18n.backend.store_translations :en, :formtastic => @formtastic_strings
38
+ end
39
+
40
+ it "should translate core strings correctly" do
41
+ ::Formtastic::I18n.t(:required).should == "Default Required"
42
+ ::Formtastic::I18n.t(:yes).should == "Default Yes"
43
+ ::Formtastic::I18n.t(:no).should == "Default No"
44
+ ::Formtastic::I18n.t(:create, :model => 'Post').should == "Default Create Post"
45
+ ::Formtastic::I18n.t(:update, :model => 'Post').should == "Default Update Post"
46
+ end
47
+
48
+ it "should all belong to scope 'formtastic'" do
49
+ ::Formtastic::I18n.t(:duck, :scope => [:custom_scope]).should == 'Duck'
50
+ end
51
+
52
+ it "should override default I18n lookup args if these are specified" do
53
+ ::Formtastic::I18n.t(:duck_pond, :scope => [:custom_scope], :ducks => 15).should == '15 ducks in a pond'
54
+ end
55
+
56
+ it "should be possible to override default values" do
57
+ ::I18n.backend.store_translations :en, {:formtastic => {:required => nil}}
58
+ ::Formtastic::I18n.t(:required, :default => 'Nothing found!').should == 'Nothing found!'
59
+ end
60
+
61
+ end
62
+
63
+ describe "when no I18n locales are available" do
64
+
65
+ before do
66
+ ::I18n.backend.store_translations :en, :formtastic => {
67
+ :required => nil,
68
+ :yes => nil,
69
+ :no => nil,
70
+ :create => nil,
71
+ :update => nil
72
+ }
73
+ end
74
+
75
+ it "should use default strings" do
76
+ (::Formtastic::I18n::DEFAULT_VALUES.keys).each do |key|
77
+ ::Formtastic::I18n.t(key, :model => '{{model}}').should == ::Formtastic::I18n::DEFAULT_VALUES[key]
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ describe "I18n string lookups" do
84
+
85
+ include FormtasticSpecHelper
86
+
87
+ before do
88
+ @output_buffer = ''
89
+ mock_everything
90
+
91
+ ::I18n.backend.store_translations :en, :formtastic => {
92
+ :labels => {
93
+ :title => "Hello world!",
94
+ :post => {:title => "Hello post!"},
95
+ :project => {:title => "Hello project!"}
96
+ }
97
+ }
98
+ ::Formtastic::SemanticFormBuilder.i18n_lookups_by_default = true
99
+
100
+ @new_post.stub!(:title)
101
+ @new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 255))
102
+ end
103
+
104
+ after do
105
+ ::I18n.backend.store_translations :en, :formtastic => nil
106
+ ::Formtastic::SemanticFormBuilder.i18n_lookups_by_default = false
107
+ end
108
+
109
+ it "lookup scopes should be defined" do
110
+ lambda { ::Formtastic::I18n::SCOPES }.should_not raise_error(::NameError)
111
+ end
112
+
113
+ it "should be able to translate with namespaced object" do
114
+ semantic_form_for(@new_post) do |builder|
115
+ concat(builder.input(:title))
116
+ end
117
+ output_buffer.should have_tag("form label", /Hello post!/)
118
+ end
119
+
120
+ it "should be able to translate without form-object" do
121
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
122
+ concat(builder.input(:title))
123
+ end
124
+ output_buffer.should have_tag("form label", /Hello project!/)
125
+ end
126
+
127
+ # TODO: Add spec for namespaced models?
128
+
129
+ end
130
+
131
+ end
@@ -0,0 +1,70 @@
1
+ # coding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe "*select: options[:include_blank]" do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+
12
+ @new_post.stub!(:author_id).and_return(nil)
13
+ @new_post.stub!(:publish_at).and_return(nil)
14
+
15
+ @select_input_types = {
16
+ :select => :author,
17
+ :datetime => :publish_at,
18
+ :date => :publish_at,
19
+ :time => :publish_at
20
+ }
21
+ end
22
+
23
+ describe 'when :include_blank is not set' do
24
+ it 'blank value should be included if the default value specified in config is true' do
25
+ ::Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = true
26
+ @select_input_types.each do |as, attribute|
27
+ semantic_form_for(@new_post) do |builder|
28
+ concat(builder.input(attribute, :as => as))
29
+ end
30
+ output_buffer.should have_tag("form li select option[@value='']", "")
31
+ end
32
+ end
33
+
34
+ it 'blank value should not be included if the default value specified in config is false' do
35
+ ::Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = false
36
+ @select_input_types.each do |as, attribute|
37
+ semantic_form_for(@new_post) do |builder|
38
+ concat(builder.input(attribute, :as => as))
39
+ end
40
+ output_buffer.should_not have_tag("form li select option[@value='']", "")
41
+ end
42
+ end
43
+
44
+ after do
45
+ ::Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = true
46
+ end
47
+ end
48
+
49
+ describe 'when :include_blank is set to false' do
50
+ it 'should not have a blank option' do
51
+ @select_input_types.each do |as, attribute|
52
+ semantic_form_for(@new_post) do |builder|
53
+ concat(builder.input(attribute, :as => as, :include_blank => false))
54
+ end
55
+ output_buffer.should_not have_tag("form li select option[@value='']", "")
56
+ end
57
+ end
58
+ end
59
+
60
+ describe 'when :include_blank => true is set' do
61
+ it 'should have a blank select option' do
62
+ @select_input_types.each do |as, attribute|
63
+ semantic_form_for(@new_post) do |builder|
64
+ concat(builder.input(attribute, :as => as, :include_blank => true))
65
+ end
66
+ output_buffer.should have_tag("form li select option[@value='']", "")
67
+ end
68
+ end
69
+ end
70
+ end