formtastic 2.0.2 → 2.1.0.beta1

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 (116) hide show
  1. data/.gitignore +4 -1
  2. data/Appraisals +11 -0
  3. data/CHANGELOG +2 -2
  4. data/Gemfile +0 -2
  5. data/README.textile +183 -151
  6. data/Rakefile +9 -5
  7. data/app/assets/stylesheets/formtastic.css +16 -3
  8. data/formtastic.gemspec +6 -2
  9. data/gemfiles/rails-3.0.gemfile +7 -0
  10. data/gemfiles/rails-3.1.gemfile +7 -0
  11. data/gemfiles/rails-3.2.gemfile +7 -0
  12. data/lib/formtastic.rb +10 -2
  13. data/lib/formtastic/actions.rb +11 -0
  14. data/lib/formtastic/actions/base.rb +156 -0
  15. data/lib/formtastic/actions/button_action.rb +72 -0
  16. data/lib/formtastic/actions/buttonish.rb +17 -0
  17. data/lib/formtastic/actions/input_action.rb +68 -0
  18. data/lib/formtastic/actions/link_action.rb +87 -0
  19. data/lib/formtastic/engine.rb +5 -1
  20. data/lib/formtastic/form_builder.rb +3 -0
  21. data/lib/formtastic/helpers.rb +2 -1
  22. data/lib/formtastic/helpers/action_helper.rb +109 -0
  23. data/lib/formtastic/helpers/actions_helper.rb +168 -0
  24. data/lib/formtastic/helpers/buttons_helper.rb +22 -9
  25. data/lib/formtastic/helpers/errors_helper.rb +0 -54
  26. data/lib/formtastic/helpers/fieldset_wrapper.rb +10 -5
  27. data/lib/formtastic/helpers/form_helper.rb +2 -2
  28. data/lib/formtastic/helpers/input_helper.rb +1 -10
  29. data/lib/formtastic/helpers/inputs_helper.rb +6 -3
  30. data/lib/formtastic/i18n.rb +3 -2
  31. data/lib/formtastic/inputs/base.rb +11 -3
  32. data/lib/formtastic/inputs/base/choices.rb +6 -1
  33. data/lib/formtastic/inputs/base/collections.rb +36 -13
  34. data/lib/formtastic/inputs/base/grouped_collections.rb +1 -1
  35. data/lib/formtastic/inputs/base/numeric.rb +50 -0
  36. data/lib/formtastic/inputs/base/options.rb +1 -1
  37. data/lib/formtastic/inputs/base/placeholder.rb +17 -0
  38. data/lib/formtastic/inputs/base/stringish.rb +2 -7
  39. data/lib/formtastic/inputs/base/timeish.rb +21 -5
  40. data/lib/formtastic/inputs/base/validations.rb +1 -1
  41. data/lib/formtastic/inputs/base/wrapping.rb +10 -3
  42. data/lib/formtastic/inputs/boolean_input.rb +10 -2
  43. data/lib/formtastic/inputs/check_boxes_input.rb +18 -9
  44. data/lib/formtastic/inputs/country_input.rb +2 -2
  45. data/lib/formtastic/inputs/date_input.rb +19 -1
  46. data/lib/formtastic/inputs/datetime_input.rb +1 -1
  47. data/lib/formtastic/inputs/email_input.rb +2 -1
  48. data/lib/formtastic/inputs/file_input.rb +1 -1
  49. data/lib/formtastic/inputs/hidden_input.rb +1 -1
  50. data/lib/formtastic/inputs/number_input.rb +6 -36
  51. data/lib/formtastic/inputs/password_input.rb +2 -1
  52. data/lib/formtastic/inputs/phone_input.rb +3 -2
  53. data/lib/formtastic/inputs/radio_input.rb +1 -1
  54. data/lib/formtastic/inputs/range_input.rb +8 -32
  55. data/lib/formtastic/inputs/search_input.rb +2 -1
  56. data/lib/formtastic/inputs/select_input.rb +56 -28
  57. data/lib/formtastic/inputs/string_input.rb +3 -1
  58. data/lib/formtastic/inputs/text_input.rb +5 -4
  59. data/lib/formtastic/inputs/time_input.rb +4 -8
  60. data/lib/formtastic/inputs/time_zone_input.rb +1 -1
  61. data/lib/formtastic/inputs/url_input.rb +2 -1
  62. data/lib/formtastic/localized_string.rb +6 -94
  63. data/lib/formtastic/localizer.rb +110 -0
  64. data/lib/formtastic/version.rb +1 -1
  65. data/lib/generators/formtastic/form/form_generator.rb +105 -0
  66. data/lib/generators/templates/_form.html.erb +2 -2
  67. data/lib/generators/templates/_form.html.haml +4 -4
  68. data/lib/generators/templates/_form.html.slim +2 -2
  69. data/lib/generators/templates/formtastic.rb +4 -0
  70. data/lib/locale/en.yml +2 -0
  71. data/sample/basic_inputs.html +22 -0
  72. data/spec/actions/button_action_spec.rb +63 -0
  73. data/spec/actions/generic_action_spec.rb +484 -0
  74. data/spec/actions/input_action_spec.rb +59 -0
  75. data/spec/actions/link_action_spec.rb +92 -0
  76. data/spec/builder/semantic_fields_for_spec.rb +14 -0
  77. data/spec/generators/formtastic/form/form_generator_spec.rb +118 -0
  78. data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
  79. data/spec/helpers/action_helper_spec.rb +365 -0
  80. data/spec/helpers/actions_helper_spec.rb +143 -0
  81. data/spec/helpers/buttons_helper_spec.rb +39 -23
  82. data/spec/helpers/commit_button_helper_spec.rb +153 -93
  83. data/spec/helpers/inputs_helper_spec.rb +14 -0
  84. data/spec/i18n_spec.rb +11 -0
  85. data/spec/inputs/boolean_input_spec.rb +31 -2
  86. data/spec/inputs/check_boxes_input_spec.rb +29 -1
  87. data/spec/inputs/date_input_spec.rb +95 -0
  88. data/spec/inputs/datetime_input_spec.rb +49 -0
  89. data/spec/inputs/email_input_spec.rb +28 -0
  90. data/spec/inputs/file_input_spec.rb +28 -0
  91. data/spec/inputs/hidden_input_spec.rb +28 -0
  92. data/spec/inputs/include_blank_spec.rb +53 -45
  93. data/spec/inputs/number_input_spec.rb +34 -4
  94. data/spec/inputs/password_input_spec.rb +28 -0
  95. data/spec/inputs/phone_input_spec.rb +28 -0
  96. data/spec/inputs/placeholder_spec.rb +10 -10
  97. data/spec/inputs/radio_input_spec.rb +51 -6
  98. data/spec/inputs/range_input_spec.rb +30 -2
  99. data/spec/inputs/search_input_spec.rb +27 -0
  100. data/spec/inputs/select_input_spec.rb +52 -6
  101. data/spec/inputs/string_input_spec.rb +28 -0
  102. data/spec/inputs/text_input_spec.rb +27 -0
  103. data/spec/inputs/time_input_spec.rb +67 -1
  104. data/spec/inputs/time_zone_input_spec.rb +28 -0
  105. data/spec/inputs/url_input_spec.rb +28 -0
  106. data/spec/inputs/with_options_spec.rb +43 -0
  107. data/spec/spec_helper.rb +22 -6
  108. data/spec/support/custom_macros.rb +6 -134
  109. data/spec/support/test_environment.rb +0 -1
  110. metadata +104 -17
  111. data/lib/formtastic/helpers/semantic_form_helper.rb +0 -11
  112. data/lib/formtastic/inputs/numeric_input.rb +0 -21
  113. data/lib/formtastic/railtie.rb +0 -12
  114. data/lib/formtastic/semantic_form_builder.rb +0 -11
  115. data/spec/builder/errors_spec.rb +0 -203
  116. data/spec/inputs/numeric_input_spec.rb +0 -41
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'InputAction', 'when submitting' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+
12
+ concat(semantic_form_for(@new_post) do |builder|
13
+ concat(builder.action(:submit, :as => :input))
14
+ end)
15
+ end
16
+
17
+ it 'should render a submit type of input' do
18
+ output_buffer.should have_tag('li.action.input_action input[@type="submit"]')
19
+ end
20
+
21
+ end
22
+
23
+ describe 'InputAction', 'when resetting' do
24
+
25
+ include FormtasticSpecHelper
26
+
27
+ before do
28
+ @output_buffer = ''
29
+ mock_everything
30
+
31
+ concat(semantic_form_for(@new_post) do |builder|
32
+ concat(builder.action(:reset, :as => :input))
33
+ end)
34
+ end
35
+
36
+ it 'should render a reset type of input' do
37
+ output_buffer.should have_tag('li.action.input_action input[@type="reset"]')
38
+ end
39
+
40
+ end
41
+
42
+ describe 'InputAction', 'when cancelling' do
43
+
44
+ include FormtasticSpecHelper
45
+
46
+ before do
47
+ @output_buffer = ''
48
+ mock_everything
49
+ end
50
+
51
+ it 'should raise an error' do
52
+ lambda {
53
+ concat(semantic_form_for(@new_post) do |builder|
54
+ concat(builder.action(:cancel, :as => :input))
55
+ end)
56
+ }.should raise_error(Formtastic::UnsupportedMethodForAction)
57
+ end
58
+
59
+ end
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'LinkAction', 'when cancelling' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ context 'without a :url' do
14
+ before do
15
+ concat(semantic_form_for(@new_post) do |builder|
16
+ concat(builder.action(:cancel, :as => :link))
17
+ end)
18
+ end
19
+
20
+ it 'should render a submit type of input' do
21
+ output_buffer.should have_tag('li.action.link_action a[@href="javascript:history.back()"]')
22
+ end
23
+
24
+ end
25
+
26
+ context 'with a :url as String' do
27
+
28
+ before do
29
+ concat(semantic_form_for(@new_post) do |builder|
30
+ concat(builder.action(:cancel, :as => :link, :url => "http://foo.bah/baz"))
31
+ end)
32
+ end
33
+
34
+ it 'should render a submit type of input' do
35
+ output_buffer.should have_tag('li.action.link_action a[@href="http://foo.bah/baz"]')
36
+ end
37
+
38
+ end
39
+
40
+ context 'with a :url as Hash' do
41
+
42
+ before do
43
+ concat(semantic_form_for(@new_post) do |builder|
44
+ concat(builder.action(:cancel, :as => :link, :url => { :action => "foo" }))
45
+ end)
46
+ end
47
+
48
+ it 'should render a submit type of input' do
49
+ output_buffer.should have_tag('li.action.link_action a[@href="/mock/path"]')
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ describe 'LinkAction', 'when submitting' do
57
+
58
+ include FormtasticSpecHelper
59
+
60
+ before do
61
+ @output_buffer = ''
62
+ mock_everything
63
+ end
64
+
65
+ it 'should raise an error' do
66
+ lambda {
67
+ concat(semantic_form_for(@new_post) do |builder|
68
+ concat(builder.action(:submit, :as => :link))
69
+ end)
70
+ }.should raise_error(Formtastic::UnsupportedMethodForAction)
71
+ end
72
+
73
+ end
74
+
75
+ describe 'LinkAction', 'when submitting' do
76
+
77
+ include FormtasticSpecHelper
78
+
79
+ before do
80
+ @output_buffer = ''
81
+ mock_everything
82
+ end
83
+
84
+ it 'should raise an error' do
85
+ lambda {
86
+ concat(semantic_form_for(@new_post) do |builder|
87
+ concat(builder.action(:reset, :as => :link))
88
+ end)
89
+ }.should raise_error(Formtastic::UnsupportedMethodForAction)
90
+ end
91
+
92
+ end
@@ -98,6 +98,20 @@ describe 'Formtastic::FormBuilder#fields_for' do
98
98
  end)
99
99
  output_buffer.should have_tag('form fieldset.inputs #context2_post_author_1_login_input')
100
100
  end
101
+
102
+ it 'should render errors on the nested inputs' do
103
+ @errors = mock('errors')
104
+ @errors.stub!(:[]).with(:login).and_return(['oh noes'])
105
+ @bob.stub!(:errors).and_return(@errors)
106
+
107
+ concat(semantic_form_for(@new_post, :namespace => 'context2') do |builder|
108
+ concat(builder.semantic_fields_for(@bob) do |nested_builder|
109
+ concat(nested_builder.inputs(:login))
110
+ end)
111
+ end)
112
+ output_buffer.should =~ /oh noes/
113
+ end
114
+
101
115
  end
102
116
 
103
117
  context "when I rendered my own hidden id input" do
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ # Generators are not automatically loaded by Rails
4
+ require 'generators/formtastic/form/form_generator'
5
+
6
+ describe Formtastic::FormGenerator do
7
+
8
+ include FormtasticSpecHelper
9
+
10
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
11
+ destination File.expand_path("../../../../../tmp", __FILE__)
12
+
13
+ before do
14
+ @output_buffer = ''
15
+ prepare_destination
16
+ mock_everything
17
+ ::Post.stub!(:reflect_on_all_associations).with(:belongs_to).and_return([
18
+ mock('reflection', :name => :author, :options => {}, :klass => ::Author, :macro => :belongs_to),
19
+ mock('reflection', :name => :reviewer, :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to),
20
+ mock('reflection', :name => :main_post, :options => {}, :klass => ::Post, :macro => :belongs_to),
21
+ mock('reflection', :name => :attachment, :options => {:polymorphic => true}, :macro => :belongs_to),
22
+ ])
23
+ end
24
+
25
+ describe 'without model' do
26
+ it 'should raise Thor::RequiredArgumentMissingError' do
27
+ lambda { run_generator }.should raise_error(Thor::RequiredArgumentMissingError)
28
+ end
29
+ end
30
+
31
+ describe 'with existing model' do
32
+ it 'should not raise an exception' do
33
+ lambda { run_generator %w(Post) }.should_not raise_error(Thor::RequiredArgumentMissingError)
34
+ end
35
+ end
36
+
37
+ describe 'with attributes' do
38
+ before { run_generator %w(Post title:string author:references) }
39
+
40
+ describe 'render only the specified attributes' do
41
+ subject { file('app/views/posts/_form.html.erb') }
42
+ it { should exist }
43
+ it { should contain "<%= f.input :title %>" }
44
+ it { should contain "<%= f.input :author %>" }
45
+ it { should_not contain "<%= f.input :main_post %>" }
46
+ end
47
+ end
48
+
49
+ describe 'without attributes' do
50
+ before { run_generator %w(Post) }
51
+
52
+ subject { file('app/views/posts/_form.html.erb') }
53
+
54
+ describe 'content_columns' do
55
+ it { should contain "<%= f.input :title %>" }
56
+ it { should contain "<%= f.input :body %>" }
57
+ it { should_not contain "<%= f.input :created_at %>" }
58
+ it { should_not contain "<%= f.input :updated_at %>" }
59
+ end
60
+
61
+ describe 'reflection_on_association' do
62
+ it { should contain "<%= f.input :author %>" }
63
+ it { should contain "<%= f.input :reviewer %>" }
64
+ it { should contain "<%= f.input :main_post %>" }
65
+ it { should_not contain "<%= f.input :attachment %>" }
66
+ end
67
+ end
68
+
69
+ describe 'with template engine option' do
70
+ describe 'erb' do
71
+ before { run_generator %w(Post --template-engine erb) }
72
+
73
+ describe 'app/views/posts/_form.html.erb' do
74
+ subject { file('app/views/posts/_form.html.erb') }
75
+ it { should exist }
76
+ it { should contain "<%= semantic_form_for @post do |f| %>" }
77
+ end
78
+ end
79
+
80
+ describe 'haml' do
81
+ before { run_generator %w(Post --template-engine haml) }
82
+
83
+ describe 'app/views/posts/_form.html.haml' do
84
+ subject { file('app/views/posts/_form.html.haml') }
85
+ it { should exist }
86
+ it { should contain "= semantic_form_for @post do |f|" }
87
+ end
88
+ end
89
+
90
+ describe 'slim' do
91
+ before { run_generator %w(Post --template-engine slim) }
92
+
93
+ describe 'app/views/posts/_form.html.slim' do
94
+ subject { file('app/views/posts/_form.html.slim') }
95
+ it { should exist }
96
+ it { should contain "= semantic_form_for @post do |f|" }
97
+ end
98
+ end
99
+ end
100
+
101
+ describe 'with copy option' do
102
+ before { run_generator %w(Post --copy) }
103
+
104
+ describe 'app/views/posts/_form.html.erb' do
105
+ subject { file('app/views/posts/_form.html.erb') }
106
+ it { should_not exist }
107
+ end
108
+ end
109
+
110
+ describe 'with controller option' do
111
+ before { run_generator %w(Post --controller admin/posts) }
112
+
113
+ describe 'app/views/admin/posts/_form.html.erb' do
114
+ subject { file('app/views/admin/posts/_form.html.erb') }
115
+ it { should exist }
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ # Generators are not automatically loaded by Rails
4
+ require 'generators/formtastic/install/install_generator'
5
+
6
+ describe Formtastic::InstallGenerator do
7
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
8
+ destination File.expand_path("../../../../../tmp", __FILE__)
9
+
10
+ before { prepare_destination }
11
+
12
+ describe 'no arguments' do
13
+ before { run_generator }
14
+
15
+ describe 'config/initializers/formtastic.rb' do
16
+ subject { file('config/initializers/formtastic.rb') }
17
+ it { should exist }
18
+ it { should contain "# Please note: If you're subclassing Formtastic::FormBuilder" }
19
+ end
20
+
21
+ describe 'lib/templates/erb/scaffold/_form.html.erb' do
22
+ subject { file('lib/templates/erb/scaffold/_form.html.erb') }
23
+ it { should exist }
24
+ it { should contain "<%%= semantic_form_for @<%= singular_name %> do |f| %>" }
25
+ end
26
+ end
27
+
28
+ describe 'haml' do
29
+ before { run_generator %w(--template-engine haml) }
30
+
31
+ describe 'lib/templates/erb/scaffold/_form.html.haml' do
32
+ subject { file('lib/templates/haml/scaffold/_form.html.haml') }
33
+ it { should exist }
34
+ it { should contain "= semantic_form_for @<%= singular_name %> do |f|" }
35
+ end
36
+ end
37
+
38
+ describe 'slim' do
39
+ before { run_generator %w(--template-engine slim) }
40
+
41
+ describe 'lib/templates/erb/scaffold/_form.html.slim' do
42
+ subject { file('lib/templates/slim/scaffold/_form.html.slim') }
43
+ it { should exist }
44
+ it { should contain "= semantic_form_for @<%= singular_name %> do |f|" }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,365 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'Formtastic::FormBuilder#action' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ end
12
+
13
+ after do
14
+ ::I18n.backend.reload!
15
+ end
16
+
17
+ describe 'arguments and options' do
18
+
19
+ it 'should require the first argument (the action method)' do
20
+ lambda {
21
+ concat(semantic_form_for(@new_post) do |builder|
22
+ concat(builder.action()) # no args passed in at all
23
+ end)
24
+ }.should raise_error(ArgumentError)
25
+ end
26
+
27
+ describe ':as option' do
28
+
29
+ describe 'when not provided' do
30
+
31
+ it 'should default to a commit for commit' do
32
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
33
+ concat(builder.action(:submit))
34
+ end)
35
+ output_buffer.should have_tag('form li.action.input_action', :count => 1)
36
+ end
37
+
38
+ it 'should default to a button for reset' do
39
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
40
+ concat(builder.action(:reset))
41
+ end)
42
+ output_buffer.should have_tag('form li.action.input_action', :count => 1)
43
+ end
44
+
45
+ it 'should default to a link for cancel' do
46
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
47
+ concat(builder.action(:cancel))
48
+ end)
49
+ output_buffer.should have_tag('form li.action.link_action', :count => 1)
50
+ end
51
+ end
52
+
53
+ it 'should call the corresponding action class with .to_html' do
54
+ [:input, :button, :link].each do |action_style|
55
+ semantic_form_for(:project, :url => "http://test.host") do |builder|
56
+ action_instance = mock('Action instance')
57
+ action_class = "#{action_style.to_s}_action".classify
58
+ action_constant = "Formtastic::Actions::#{action_class}".constantize
59
+
60
+ action_constant.should_receive(:new).and_return(action_instance)
61
+ action_instance.should_receive(:to_html).and_return("some HTML")
62
+
63
+ concat(builder.action(:submit, :as => action_style))
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ #describe ':label option' do
71
+ #
72
+ # describe 'when provided' do
73
+ # it 'should be passed down to the label tag' do
74
+ # concat(semantic_form_for(@new_post) do |builder|
75
+ # concat(builder.input(:title, :label => "Kustom"))
76
+ # end)
77
+ # output_buffer.should have_tag("form li label", /Kustom/)
78
+ # end
79
+ #
80
+ # it 'should not generate a label if false' do
81
+ # concat(semantic_form_for(@new_post) do |builder|
82
+ # concat(builder.input(:title, :label => false))
83
+ # end)
84
+ # output_buffer.should_not have_tag("form li label")
85
+ # end
86
+ #
87
+ # it 'should be dupped if frozen' do
88
+ # concat(semantic_form_for(@new_post) do |builder|
89
+ # concat(builder.input(:title, :label => "Kustom".freeze))
90
+ # end)
91
+ # output_buffer.should have_tag("form li label", /Kustom/)
92
+ # end
93
+ # end
94
+ #
95
+ # describe 'when not provided' do
96
+ # describe 'when localized label is provided' do
97
+ # describe 'and object is given' do
98
+ # describe 'and label_str_method not :humanize' do
99
+ # it 'should render a label with localized text and not apply the label_str_method' do
100
+ # with_config :label_str_method, :reverse do
101
+ # @localized_label_text = 'Localized title'
102
+ # @new_post.stub!(:meta_description)
103
+ # ::I18n.backend.store_translations :en,
104
+ # :formtastic => {
105
+ # :labels => {
106
+ # :meta_description => @localized_label_text
107
+ # }
108
+ # }
109
+ #
110
+ # concat(semantic_form_for(@new_post) do |builder|
111
+ # concat(builder.input(:meta_description))
112
+ # end)
113
+ # output_buffer.should have_tag('form li label', /Localized title/)
114
+ # end
115
+ # end
116
+ # end
117
+ # end
118
+ # end
119
+ #
120
+ # describe 'when localized label is NOT provided' do
121
+ # describe 'and object is not given' do
122
+ # it 'should default the humanized method name, passing it down to the label tag' do
123
+ # ::I18n.backend.store_translations :en, :formtastic => {}
124
+ # with_config :label_str_method, :humanize do
125
+ # concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
126
+ # concat(builder.input(:meta_description))
127
+ # end)
128
+ # output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
129
+ # end
130
+ # end
131
+ # end
132
+ #
133
+ # describe 'and object is given' do
134
+ # it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
135
+ # @new_post.stub!(:meta_description) # a two word method name
136
+ # @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
137
+ #
138
+ # concat(semantic_form_for(@new_post) do |builder|
139
+ # concat(builder.input(:meta_description))
140
+ # end)
141
+ # output_buffer.should have_tag("form li label", /#{'meta_description'.humanize}/)
142
+ # end
143
+ # end
144
+ #
145
+ # describe 'and object is given with label_str_method set to :capitalize' do
146
+ # it 'should capitalize method name, passing it down to the label tag' do
147
+ # with_config :label_str_method, :capitalize do
148
+ # @new_post.stub!(:meta_description)
149
+ #
150
+ # concat(semantic_form_for(@new_post) do |builder|
151
+ # concat(builder.input(:meta_description))
152
+ # end)
153
+ # output_buffer.should have_tag("form li label", /#{'meta_description'.capitalize}/)
154
+ # end
155
+ # end
156
+ # end
157
+ # end
158
+ #
159
+ # describe 'when localized label is provided' do
160
+ # before do
161
+ # @localized_label_text = 'Localized title'
162
+ # @default_localized_label_text = 'Default localized title'
163
+ # ::I18n.backend.store_translations :en,
164
+ # :formtastic => {
165
+ # :labels => {
166
+ # :title => @default_localized_label_text,
167
+ # :published => @default_localized_label_text,
168
+ # :post => {
169
+ # :title => @localized_label_text,
170
+ # :published => @default_localized_label_text
171
+ # }
172
+ # }
173
+ # }
174
+ # end
175
+ #
176
+ # it 'should render a label with localized label (I18n)' do
177
+ # with_config :i18n_lookups_by_default, false do
178
+ # concat(semantic_form_for(@new_post) do |builder|
179
+ # concat(builder.input(:title, :label => true))
180
+ # concat(builder.input(:published, :as => :boolean, :label => true))
181
+ # end)
182
+ # output_buffer.should have_tag('form li label', Regexp.new('^' + @localized_label_text))
183
+ # end
184
+ # end
185
+ #
186
+ # it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
187
+ # with_config :i18n_lookups_by_default, false do
188
+ # ::I18n.backend.store_translations :en,
189
+ # :formtastic => {
190
+ # :labels => {
191
+ # :post => {
192
+ # :title => nil,
193
+ # :published => nil
194
+ # }
195
+ # }
196
+ # }
197
+ # concat(semantic_form_for(@new_post) do |builder|
198
+ # concat(builder.input(:title, :label => true))
199
+ # concat(builder.input(:published, :as => :boolean, :label => true))
200
+ # end)
201
+ # output_buffer.should have_tag('form li label', Regexp.new('^' + @default_localized_label_text))
202
+ # end
203
+ # end
204
+ # end
205
+ # end
206
+ #
207
+ #end
208
+ #
209
+ describe ':wrapper_html option' do
210
+
211
+ describe 'when provided' do
212
+ it 'should be passed down to the li tag' do
213
+ concat(semantic_form_for(@new_post) do |builder|
214
+ concat(builder.action(:submit, :wrapper_html => {:id => :another_id}))
215
+ end)
216
+ output_buffer.should have_tag("form li#another_id")
217
+ end
218
+
219
+ it 'should append given classes to li default classes' do
220
+ concat(semantic_form_for(@new_post) do |builder|
221
+ concat(builder.action(:submit, :wrapper_html => {:class => :another_class}))
222
+ end)
223
+ output_buffer.should have_tag("form li.action")
224
+ output_buffer.should have_tag("form li.input_action")
225
+ output_buffer.should have_tag("form li.another_class")
226
+ end
227
+
228
+ it 'should allow classes to be an array' do
229
+ concat(semantic_form_for(@new_post) do |builder|
230
+ concat(builder.action(:submit, :wrapper_html => {:class => [ :my_class, :another_class ]}))
231
+ end)
232
+ output_buffer.should have_tag("form li.action")
233
+ output_buffer.should have_tag("form li.input_action")
234
+ output_buffer.should have_tag("form li.my_class")
235
+ output_buffer.should have_tag("form li.another_class")
236
+ end
237
+ end
238
+
239
+ describe 'when not provided' do
240
+ it 'should use default id and class' do
241
+ concat(semantic_form_for(@new_post) do |builder|
242
+ concat(builder.action(:submit))
243
+ end)
244
+ output_buffer.should have_tag("form li#post_submit_action")
245
+ output_buffer.should have_tag("form li.action")
246
+ output_buffer.should have_tag("form li.input_action")
247
+ end
248
+ end
249
+
250
+ end
251
+
252
+ end
253
+
254
+ describe 'instantiating an action class' do
255
+
256
+ context 'when a class does not exist' do
257
+ it "should raise an error" do
258
+ lambda {
259
+ concat(semantic_form_for(@new_post) do |builder|
260
+ builder.action(:submit, :as => :non_existant)
261
+ end)
262
+ }.should raise_error(Formtastic::UnknownActionError)
263
+ end
264
+ end
265
+
266
+ context 'when a customized top-level class does not exist' do
267
+
268
+ it 'should instantiate the Formtastic action' do
269
+ action = mock('action', :to_html => 'some HTML')
270
+ Formtastic::Actions::ButtonAction.should_receive(:new).and_return(action)
271
+ concat(semantic_form_for(@new_post) do |builder|
272
+ builder.action(:commit, :as => :button)
273
+ end)
274
+ end
275
+
276
+ end
277
+
278
+ describe 'when a top-level (custom) action class exists' do
279
+ it "should instantiate the top-level action instead of the Formtastic one" do
280
+ class ::ButtonAction < Formtastic::Actions::ButtonAction
281
+ end
282
+
283
+ action = mock('action', :to_html => 'some HTML')
284
+ Formtastic::Actions::ButtonAction.should_not_receive(:new).and_return(action)
285
+ ::ButtonAction.should_receive(:new).and_return(action)
286
+
287
+ concat(semantic_form_for(@new_post) do |builder|
288
+ builder.action(:commit, :as => :button)
289
+ end)
290
+ end
291
+ end
292
+
293
+ describe 'when instantiated multiple times with the same action type' do
294
+
295
+ it "should be cached (not calling the internal methods)" do
296
+ # TODO this is really tied to the underlying implementation
297
+ concat(semantic_form_for(@new_post) do |builder|
298
+ builder.should_receive(:custom_action_class_name).with(:button).once.and_return(::Formtastic::Actions::ButtonAction)
299
+ builder.action(:submit, :as => :button)
300
+ builder.action(:submit, :as => :button)
301
+ end)
302
+ end
303
+
304
+ end
305
+
306
+ describe 'support for :as on each action' do
307
+
308
+ it "should raise an error when the action does not support the :as" do
309
+ lambda {
310
+ concat(semantic_form_for(@new_post) do |builder|
311
+ concat(builder.action(:submit, :as => :link))
312
+ end)
313
+ }.should raise_error(Formtastic::UnsupportedMethodForAction)
314
+
315
+ lambda {
316
+ concat(semantic_form_for(@new_post) do |builder|
317
+ concat(builder.action(:cancel, :as => :input))
318
+ end)
319
+ }.should raise_error(Formtastic::UnsupportedMethodForAction)
320
+
321
+ lambda {
322
+ concat(semantic_form_for(@new_post) do |builder|
323
+ concat(builder.action(:cancel, :as => :button))
324
+ end)
325
+ }.should raise_error(Formtastic::UnsupportedMethodForAction)
326
+ end
327
+
328
+ it "should not raise an error when the action does not support the :as" do
329
+ lambda {
330
+ concat(semantic_form_for(@new_post) do |builder|
331
+ concat(builder.action(:cancel, :as => :link))
332
+ end)
333
+ }.should_not raise_error(Formtastic::UnsupportedMethodForAction)
334
+
335
+ lambda {
336
+ concat(semantic_form_for(@new_post) do |builder|
337
+ concat(builder.action(:submit, :as => :input))
338
+ end)
339
+ }.should_not raise_error(Formtastic::UnsupportedMethodForAction)
340
+
341
+ lambda {
342
+ concat(semantic_form_for(@new_post) do |builder|
343
+ concat(builder.action(:submit, :as => :button))
344
+ end)
345
+ }.should_not raise_error(Formtastic::UnsupportedMethodForAction)
346
+
347
+ lambda {
348
+ concat(semantic_form_for(@new_post) do |builder|
349
+ concat(builder.action(:reset, :as => :input))
350
+ end)
351
+ }.should_not raise_error(Formtastic::UnsupportedMethodForAction)
352
+
353
+ lambda {
354
+ concat(semantic_form_for(@new_post) do |builder|
355
+ concat(builder.action(:reset, :as => :button))
356
+ end)
357
+ }.should_not raise_error(Formtastic::UnsupportedMethodForAction)
358
+ end
359
+
360
+ end
361
+
362
+ end
363
+
364
+ end
365
+