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.
- data/.gitignore +4 -1
- data/Appraisals +11 -0
- data/CHANGELOG +2 -2
- data/Gemfile +0 -2
- data/README.textile +183 -151
- data/Rakefile +9 -5
- data/app/assets/stylesheets/formtastic.css +16 -3
- data/formtastic.gemspec +6 -2
- data/gemfiles/rails-3.0.gemfile +7 -0
- data/gemfiles/rails-3.1.gemfile +7 -0
- data/gemfiles/rails-3.2.gemfile +7 -0
- data/lib/formtastic.rb +10 -2
- data/lib/formtastic/actions.rb +11 -0
- data/lib/formtastic/actions/base.rb +156 -0
- data/lib/formtastic/actions/button_action.rb +72 -0
- data/lib/formtastic/actions/buttonish.rb +17 -0
- data/lib/formtastic/actions/input_action.rb +68 -0
- data/lib/formtastic/actions/link_action.rb +87 -0
- data/lib/formtastic/engine.rb +5 -1
- data/lib/formtastic/form_builder.rb +3 -0
- data/lib/formtastic/helpers.rb +2 -1
- data/lib/formtastic/helpers/action_helper.rb +109 -0
- data/lib/formtastic/helpers/actions_helper.rb +168 -0
- data/lib/formtastic/helpers/buttons_helper.rb +22 -9
- data/lib/formtastic/helpers/errors_helper.rb +0 -54
- data/lib/formtastic/helpers/fieldset_wrapper.rb +10 -5
- data/lib/formtastic/helpers/form_helper.rb +2 -2
- data/lib/formtastic/helpers/input_helper.rb +1 -10
- data/lib/formtastic/helpers/inputs_helper.rb +6 -3
- data/lib/formtastic/i18n.rb +3 -2
- data/lib/formtastic/inputs/base.rb +11 -3
- data/lib/formtastic/inputs/base/choices.rb +6 -1
- data/lib/formtastic/inputs/base/collections.rb +36 -13
- data/lib/formtastic/inputs/base/grouped_collections.rb +1 -1
- data/lib/formtastic/inputs/base/numeric.rb +50 -0
- data/lib/formtastic/inputs/base/options.rb +1 -1
- data/lib/formtastic/inputs/base/placeholder.rb +17 -0
- data/lib/formtastic/inputs/base/stringish.rb +2 -7
- data/lib/formtastic/inputs/base/timeish.rb +21 -5
- data/lib/formtastic/inputs/base/validations.rb +1 -1
- data/lib/formtastic/inputs/base/wrapping.rb +10 -3
- data/lib/formtastic/inputs/boolean_input.rb +10 -2
- data/lib/formtastic/inputs/check_boxes_input.rb +18 -9
- data/lib/formtastic/inputs/country_input.rb +2 -2
- data/lib/formtastic/inputs/date_input.rb +19 -1
- data/lib/formtastic/inputs/datetime_input.rb +1 -1
- data/lib/formtastic/inputs/email_input.rb +2 -1
- data/lib/formtastic/inputs/file_input.rb +1 -1
- data/lib/formtastic/inputs/hidden_input.rb +1 -1
- data/lib/formtastic/inputs/number_input.rb +6 -36
- data/lib/formtastic/inputs/password_input.rb +2 -1
- data/lib/formtastic/inputs/phone_input.rb +3 -2
- data/lib/formtastic/inputs/radio_input.rb +1 -1
- data/lib/formtastic/inputs/range_input.rb +8 -32
- data/lib/formtastic/inputs/search_input.rb +2 -1
- data/lib/formtastic/inputs/select_input.rb +56 -28
- data/lib/formtastic/inputs/string_input.rb +3 -1
- data/lib/formtastic/inputs/text_input.rb +5 -4
- data/lib/formtastic/inputs/time_input.rb +4 -8
- data/lib/formtastic/inputs/time_zone_input.rb +1 -1
- data/lib/formtastic/inputs/url_input.rb +2 -1
- data/lib/formtastic/localized_string.rb +6 -94
- data/lib/formtastic/localizer.rb +110 -0
- data/lib/formtastic/version.rb +1 -1
- data/lib/generators/formtastic/form/form_generator.rb +105 -0
- data/lib/generators/templates/_form.html.erb +2 -2
- data/lib/generators/templates/_form.html.haml +4 -4
- data/lib/generators/templates/_form.html.slim +2 -2
- data/lib/generators/templates/formtastic.rb +4 -0
- data/lib/locale/en.yml +2 -0
- data/sample/basic_inputs.html +22 -0
- data/spec/actions/button_action_spec.rb +63 -0
- data/spec/actions/generic_action_spec.rb +484 -0
- data/spec/actions/input_action_spec.rb +59 -0
- data/spec/actions/link_action_spec.rb +92 -0
- data/spec/builder/semantic_fields_for_spec.rb +14 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +118 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
- data/spec/helpers/action_helper_spec.rb +365 -0
- data/spec/helpers/actions_helper_spec.rb +143 -0
- data/spec/helpers/buttons_helper_spec.rb +39 -23
- data/spec/helpers/commit_button_helper_spec.rb +153 -93
- data/spec/helpers/inputs_helper_spec.rb +14 -0
- data/spec/i18n_spec.rb +11 -0
- data/spec/inputs/boolean_input_spec.rb +31 -2
- data/spec/inputs/check_boxes_input_spec.rb +29 -1
- data/spec/inputs/date_input_spec.rb +95 -0
- data/spec/inputs/datetime_input_spec.rb +49 -0
- data/spec/inputs/email_input_spec.rb +28 -0
- data/spec/inputs/file_input_spec.rb +28 -0
- data/spec/inputs/hidden_input_spec.rb +28 -0
- data/spec/inputs/include_blank_spec.rb +53 -45
- data/spec/inputs/number_input_spec.rb +34 -4
- data/spec/inputs/password_input_spec.rb +28 -0
- data/spec/inputs/phone_input_spec.rb +28 -0
- data/spec/inputs/placeholder_spec.rb +10 -10
- data/spec/inputs/radio_input_spec.rb +51 -6
- data/spec/inputs/range_input_spec.rb +30 -2
- data/spec/inputs/search_input_spec.rb +27 -0
- data/spec/inputs/select_input_spec.rb +52 -6
- data/spec/inputs/string_input_spec.rb +28 -0
- data/spec/inputs/text_input_spec.rb +27 -0
- data/spec/inputs/time_input_spec.rb +67 -1
- data/spec/inputs/time_zone_input_spec.rb +28 -0
- data/spec/inputs/url_input_spec.rb +28 -0
- data/spec/inputs/with_options_spec.rb +43 -0
- data/spec/spec_helper.rb +22 -6
- data/spec/support/custom_macros.rb +6 -134
- data/spec/support/test_environment.rb +0 -1
- metadata +104 -17
- data/lib/formtastic/helpers/semantic_form_helper.rb +0 -11
- data/lib/formtastic/inputs/numeric_input.rb +0 -21
- data/lib/formtastic/railtie.rb +0 -12
- data/lib/formtastic/semantic_form_builder.rb +0 -11
- data/spec/builder/errors_spec.rb +0 -203
- 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
|
+
|