formtastic 1.2.5 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +2 -0
  3. data/.yardopts +1 -0
  4. data/CHANGELOG +279 -0
  5. data/Gemfile +3 -0
  6. data/README.textile +155 -172
  7. data/RELEASE_PROCESS +7 -0
  8. data/Rakefile +52 -0
  9. data/app/assets/stylesheets/formtastic.css +275 -0
  10. data/app/assets/stylesheets/formtastic_ie6.css +27 -0
  11. data/app/assets/stylesheets/formtastic_ie7.css +17 -0
  12. data/formtastic.gemspec +51 -0
  13. data/lib/formtastic.rb +21 -1960
  14. data/lib/formtastic/engine.rb +7 -0
  15. data/lib/formtastic/form_builder.rb +83 -0
  16. data/lib/formtastic/helpers.rb +16 -0
  17. data/lib/formtastic/helpers/buttons_helper.rb +277 -0
  18. data/lib/formtastic/helpers/errors_helper.rb +113 -0
  19. data/lib/formtastic/helpers/fieldset_wrapper.rb +75 -0
  20. data/lib/formtastic/helpers/file_column_detection.rb +16 -0
  21. data/lib/formtastic/helpers/form_helper.rb +198 -0
  22. data/lib/formtastic/helpers/input_helper.rb +366 -0
  23. data/lib/formtastic/helpers/inputs_helper.rb +392 -0
  24. data/lib/formtastic/helpers/reflection.rb +33 -0
  25. data/lib/formtastic/helpers/semantic_form_helper.rb +11 -0
  26. data/lib/formtastic/html_attributes.rb +21 -0
  27. data/lib/formtastic/i18n.rb +1 -0
  28. data/lib/formtastic/inputs.rb +31 -0
  29. data/lib/formtastic/inputs/base.rb +61 -0
  30. data/lib/formtastic/inputs/base/associations.rb +31 -0
  31. data/lib/formtastic/inputs/base/choices.rb +103 -0
  32. data/lib/formtastic/inputs/base/collections.rb +94 -0
  33. data/lib/formtastic/inputs/base/database.rb +17 -0
  34. data/lib/formtastic/inputs/base/errors.rb +58 -0
  35. data/lib/formtastic/inputs/base/fileish.rb +23 -0
  36. data/lib/formtastic/inputs/base/grouped_collections.rb +77 -0
  37. data/lib/formtastic/inputs/base/hints.rb +31 -0
  38. data/lib/formtastic/inputs/base/html.rb +52 -0
  39. data/lib/formtastic/inputs/base/labelling.rb +55 -0
  40. data/lib/formtastic/inputs/base/naming.rb +42 -0
  41. data/lib/formtastic/inputs/base/options.rb +18 -0
  42. data/lib/formtastic/inputs/base/stringish.rb +35 -0
  43. data/lib/formtastic/inputs/base/timeish.rb +128 -0
  44. data/lib/formtastic/inputs/base/validations.rb +166 -0
  45. data/lib/formtastic/inputs/base/wrapping.rb +40 -0
  46. data/lib/formtastic/inputs/boolean_input.rb +96 -0
  47. data/lib/formtastic/inputs/check_boxes_input.rb +179 -0
  48. data/lib/formtastic/inputs/country_input.rb +66 -0
  49. data/lib/formtastic/inputs/date_input.rb +14 -0
  50. data/lib/formtastic/inputs/datetime_input.rb +9 -0
  51. data/lib/formtastic/inputs/email_input.rb +40 -0
  52. data/lib/formtastic/inputs/file_input.rb +42 -0
  53. data/lib/formtastic/inputs/hidden_input.rb +66 -0
  54. data/lib/formtastic/inputs/number_input.rb +118 -0
  55. data/lib/formtastic/inputs/numeric_input.rb +21 -0
  56. data/lib/formtastic/inputs/password_input.rb +40 -0
  57. data/lib/formtastic/inputs/phone_input.rb +41 -0
  58. data/lib/formtastic/inputs/radio_input.rb +157 -0
  59. data/lib/formtastic/inputs/range_input.rb +119 -0
  60. data/lib/formtastic/inputs/search_input.rb +40 -0
  61. data/lib/formtastic/inputs/select_input.rb +210 -0
  62. data/lib/formtastic/inputs/string_input.rb +34 -0
  63. data/lib/formtastic/inputs/text_input.rb +47 -0
  64. data/lib/formtastic/inputs/time_input.rb +14 -0
  65. data/lib/formtastic/inputs/time_zone_input.rb +48 -0
  66. data/lib/formtastic/inputs/url_input.rb +40 -0
  67. data/lib/formtastic/localized_string.rb +105 -0
  68. data/lib/formtastic/railtie.rb +5 -7
  69. data/lib/formtastic/semantic_form_builder.rb +11 -0
  70. data/lib/formtastic/util.rb +6 -19
  71. data/lib/formtastic/version.rb +3 -0
  72. data/lib/generators/formtastic/install/install_generator.rb +28 -6
  73. data/lib/generators/templates/_form.html.erb +10 -4
  74. data/lib/generators/templates/_form.html.haml +8 -4
  75. data/lib/generators/templates/formtastic.rb +25 -32
  76. data/lib/locale/en.yml +1 -0
  77. data/lib/tasks/verify_rcov.rb +44 -0
  78. data/sample/basic_inputs.html +182 -0
  79. data/sample/config.ru +69 -0
  80. data/sample/index.html +14 -0
  81. data/spec/builder/custom_builder_spec.rb +109 -0
  82. data/spec/builder/error_proc_spec.rb +27 -0
  83. data/spec/builder/errors_spec.rb +193 -0
  84. data/spec/builder/semantic_fields_for_spec.rb +88 -0
  85. data/spec/helpers/buttons_helper_spec.rb +150 -0
  86. data/spec/helpers/commit_button_helper_spec.rb +470 -0
  87. data/spec/helpers/form_helper_spec.rb +135 -0
  88. data/spec/helpers/input_helper_spec.rb +837 -0
  89. data/spec/helpers/inputs_helper_spec.rb +562 -0
  90. data/spec/helpers/semantic_errors_helper_spec.rb +112 -0
  91. data/spec/i18n_spec.rb +199 -0
  92. data/spec/inputs/boolean_input_spec.rb +184 -0
  93. data/spec/inputs/check_boxes_input_spec.rb +375 -0
  94. data/spec/inputs/country_input_spec.rb +133 -0
  95. data/spec/inputs/custom_input_spec.rb +52 -0
  96. data/spec/inputs/date_input_spec.rb +110 -0
  97. data/spec/inputs/datetime_input_spec.rb +115 -0
  98. data/spec/inputs/email_input_spec.rb +55 -0
  99. data/spec/inputs/file_input_spec.rb +59 -0
  100. data/spec/inputs/hidden_input_spec.rb +120 -0
  101. data/spec/inputs/include_blank_spec.rb +70 -0
  102. data/spec/inputs/label_spec.rb +104 -0
  103. data/spec/inputs/number_input_spec.rb +487 -0
  104. data/spec/inputs/numeric_input_spec.rb +41 -0
  105. data/spec/inputs/password_input_spec.rb +69 -0
  106. data/spec/inputs/phone_input_spec.rb +55 -0
  107. data/spec/inputs/placeholder_spec.rb +71 -0
  108. data/spec/inputs/radio_input_spec.rb +234 -0
  109. data/spec/inputs/range_input_spec.rb +477 -0
  110. data/spec/inputs/search_input_spec.rb +55 -0
  111. data/spec/inputs/select_input_spec.rb +545 -0
  112. data/spec/inputs/string_input_spec.rb +163 -0
  113. data/spec/inputs/text_input_spec.rb +158 -0
  114. data/spec/inputs/time_input_spec.rb +155 -0
  115. data/spec/inputs/time_zone_input_spec.rb +87 -0
  116. data/spec/inputs/url_input_spec.rb +55 -0
  117. data/spec/spec.opts +2 -0
  118. data/spec/spec_helper.rb +361 -0
  119. data/spec/support/custom_macros.rb +656 -0
  120. data/spec/support/deferred_garbage_collection.rb +21 -0
  121. data/spec/support/deprecation.rb +6 -0
  122. data/spec/support/test_environment.rb +30 -0
  123. metadata +306 -88
  124. data/generators/form/USAGE +0 -16
  125. data/generators/form/form_generator.rb +0 -111
  126. data/generators/formtastic/formtastic_generator.rb +0 -26
  127. data/init.rb +0 -5
  128. data/lib/formtastic/layout_helper.rb +0 -12
  129. data/lib/generators/formtastic/form/form_generator.rb +0 -84
  130. data/lib/generators/templates/formtastic.css +0 -145
  131. data/lib/generators/templates/formtastic_changes.css +0 -14
  132. data/lib/generators/templates/rails2/_form.html.erb +0 -5
  133. data/lib/generators/templates/rails2/_form.html.haml +0 -4
  134. data/rails/init.rb +0 -2
@@ -0,0 +1,112 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'Formtastic::FormBuilder#semantic_errors' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ @title_errors = ['must not be blank', 'must be awesome']
12
+ @base_errors = ['base error message', 'nasty error']
13
+ @base_error = 'one base error'
14
+ @errors = mock('errors')
15
+ @new_post.stub!(:errors).and_return(@errors)
16
+ end
17
+
18
+ describe 'when there is only one error on base' do
19
+ before do
20
+ @errors.stub!(:[]).with(:base).and_return(@base_error)
21
+ end
22
+
23
+ it 'should render an unordered list' do
24
+ semantic_form_for(@new_post) do |builder|
25
+ builder.semantic_errors.should have_tag('ul.errors li', @base_error)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe 'when there is more than one error on base' do
31
+ before do
32
+ @errors.stub!(:[]).with(:base).and_return(@base_errors)
33
+ end
34
+
35
+ it 'should render an unordered list' do
36
+ semantic_form_for(@new_post) do |builder|
37
+ builder.semantic_errors.should have_tag('ul.errors')
38
+ @base_errors.each do |error|
39
+ builder.semantic_errors.should have_tag('ul.errors li', error)
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ describe 'when there are errors on title' do
46
+ before do
47
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
48
+ @errors.stub!(:[]).with(:base).and_return([])
49
+ end
50
+
51
+ it 'should render an unordered list' do
52
+ semantic_form_for(@new_post) do |builder|
53
+ title_name = builder.send(:localized_string, :title, :title, :label) || builder.send(:humanized_attribute_name, :title)
54
+ builder.semantic_errors(:title).should have_tag('ul.errors li', title_name << " " << @title_errors.to_sentence)
55
+ end
56
+ end
57
+ end
58
+
59
+ describe 'when there are errors on title and base' do
60
+ before do
61
+ @errors.stub!(:[]).with(:title).and_return(@title_errors)
62
+ @errors.stub!(:[]).with(:base).and_return(@base_error)
63
+ end
64
+
65
+ it 'should render an unordered list' do
66
+ semantic_form_for(@new_post) do |builder|
67
+ title_name = builder.send(:localized_string, :title, :title, :label) || builder.send(:humanized_attribute_name, :title)
68
+ builder.semantic_errors(:title).should have_tag('ul.errors li', title_name << " " << @title_errors.to_sentence)
69
+ builder.semantic_errors(:title).should have_tag('ul.errors li', @base_error)
70
+ end
71
+ end
72
+ end
73
+
74
+ describe 'when there are no errors' do
75
+ before do
76
+ @errors.stub!(:[]).with(:title).and_return(nil)
77
+ @errors.stub!(:[]).with(:base).and_return(nil)
78
+ end
79
+
80
+ it 'should return nil' do
81
+ semantic_form_for(@new_post) do |builder|
82
+ builder.semantic_errors(:title).should be_nil
83
+ end
84
+ end
85
+ end
86
+
87
+ describe 'when there is one error on base and options with class is passed' do
88
+ before do
89
+ @errors.stub!(:[]).with(:base).and_return(@base_error)
90
+ end
91
+
92
+ it 'should render an unordered list with given class' do
93
+ semantic_form_for(@new_post) do |builder|
94
+ builder.semantic_errors(:class => "awesome").should have_tag('ul.awesome li', @base_error)
95
+ end
96
+ end
97
+ end
98
+
99
+ describe 'when :base is passed in as an argument' do
100
+ before do
101
+ @errors.stub!(:[]).with(:base).and_return(@base_error)
102
+ end
103
+
104
+ it 'should ignore :base and only render base errors once' do
105
+ semantic_form_for(@new_post) do |builder|
106
+ builder.semantic_errors(:base).should have_tag('ul li', :count => 1)
107
+ builder.semantic_errors(:base).should_not have_tag('ul li', "Base #{@base_error}")
108
+ end
109
+ end
110
+ end
111
+
112
+ end
data/spec/i18n_spec.rb ADDED
@@ -0,0 +1,199 @@
1
+ # encoding: utf-8
2
+ require '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
+ :yes => 'Default Yes',
28
+ :no => 'Default No',
29
+ :create => 'Default Create %{model}',
30
+ :update => 'Default Update %{model}',
31
+ :custom_scope => {
32
+ :duck => 'Duck',
33
+ :duck_pond => '%{ducks} ducks in a pond'
34
+ }
35
+ }
36
+ ::I18n.backend.store_translations :en, :formtastic => @formtastic_strings
37
+ end
38
+
39
+ after do
40
+ ::I18n.backend.reload!
41
+ end
42
+
43
+ it "should translate core strings correctly" do
44
+ ::I18n.backend.store_translations :en, {:formtastic => {:required => 'Default Required'}}
45
+ Formtastic::I18n.t(:required).should == "Default Required"
46
+ Formtastic::I18n.t(:yes).should == "Default Yes"
47
+ Formtastic::I18n.t(:no).should == "Default No"
48
+ Formtastic::I18n.t(:create, :model => 'Post').should == "Default Create Post"
49
+ Formtastic::I18n.t(:update, :model => 'Post').should == "Default Update Post"
50
+ end
51
+
52
+ it "should all belong to scope 'formtastic'" do
53
+ Formtastic::I18n.t(:duck, :scope => [:custom_scope]).should == 'Duck'
54
+ end
55
+
56
+ it "should override default I18n lookup args if these are specified" do
57
+ Formtastic::I18n.t(:duck_pond, :scope => [:custom_scope], :ducks => 15).should == '15 ducks in a pond'
58
+ end
59
+
60
+ it "should be possible to override default values" do
61
+ Formtastic::I18n.t(:required, :default => 'Nothing found!').should == 'Nothing found!'
62
+ end
63
+
64
+ end
65
+
66
+ describe "when no I18n locales are available" do
67
+
68
+ before do
69
+ ::I18n.backend.reload!
70
+ end
71
+
72
+ it "should use default strings" do
73
+ (Formtastic::I18n::DEFAULT_VALUES.keys).each do |key|
74
+ Formtastic::I18n.t(key, :model => '%{model}').should == Formtastic::I18n::DEFAULT_VALUES[key]
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ describe "I18n string lookups" do
81
+
82
+ include FormtasticSpecHelper
83
+
84
+ before do
85
+ @output_buffer = ''
86
+ mock_everything
87
+
88
+ ::I18n.backend.store_translations :en, {:formtastic => {
89
+ :labels => {
90
+ :author => { :name => "Top author name transation" },
91
+ :post => {:title => "Hello post!", :author => {:name => "Hello author name!"}},
92
+ :project => {:title => "Hello project!"},
93
+ }
94
+ }, :helpers => {
95
+ :label => {
96
+ :post => {:body => "Elaborate..." },
97
+ :author => { :login => "Hello login" }
98
+ }
99
+ }}
100
+
101
+ @new_post.stub!(:title)
102
+ @new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 255))
103
+ end
104
+
105
+ after do
106
+ ::I18n.backend.reload!
107
+ end
108
+
109
+ it "lookup scopes should be defined" do
110
+ with_config :i18n_lookups_by_default, true do
111
+ lambda { Formtastic::I18n::SCOPES }.should_not raise_error(::NameError)
112
+ end
113
+ end
114
+
115
+ it "should be able to translate with namespaced object" do
116
+ with_config :i18n_lookups_by_default, true do
117
+ concat(semantic_form_for(@new_post) do |builder|
118
+ concat(builder.input(:title))
119
+ end)
120
+ output_buffer.should have_tag("form label", /Hello post!/)
121
+ end
122
+ end
123
+
124
+ it "should be able to translate without form-object" do
125
+ with_config :i18n_lookups_by_default, true do
126
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
127
+ concat(builder.input(:title))
128
+ end)
129
+ output_buffer.should have_tag("form label", /Hello project!/)
130
+ end
131
+ end
132
+
133
+ it "should be able to translate when method name is same as model" do
134
+ with_config :i18n_lookups_by_default, true do
135
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
136
+ concat(builder.input(:author))
137
+ end)
138
+ output_buffer.should have_tag("form label", /Author/)
139
+ end
140
+ end
141
+
142
+ it 'should be able to translate nested objects with nested translations' do
143
+ with_config :i18n_lookups_by_default, true do
144
+ concat(semantic_form_for(@new_post) do |builder|
145
+ concat(builder.semantic_fields_for(:author) do |f|
146
+ concat(f.input(:name))
147
+ end)
148
+ end)
149
+ output_buffer.should have_tag("form label", /Hello author name!/)
150
+ end
151
+ end
152
+
153
+ it 'should be able to translate nested objects with top level translations' do
154
+ with_config :i18n_lookups_by_default, true do
155
+ concat(semantic_form_for(@new_post) do |builder|
156
+ builder.semantic_fields_for(:author) do |f|
157
+ concat(f.input(:name))
158
+ end
159
+ end)
160
+ output_buffer.should have_tag("form label", /Hello author name!/)
161
+ end
162
+ end
163
+
164
+ it 'should be able to translate nested forms with top level translations' do
165
+ with_config :i18n_lookups_by_default, true do
166
+ concat(semantic_form_for(:post) do |builder|
167
+ builder.semantic_fields_for(:author) do |f|
168
+ concat(f.input(:name))
169
+ end
170
+ end)
171
+ output_buffer.should have_tag("form label", /Hello author name!/)
172
+ end
173
+ end
174
+
175
+ it 'should be able to translate helper label as Rails does' do
176
+ with_config :i18n_lookups_by_default, true do
177
+ concat(semantic_form_for(@new_post) do |builder|
178
+ concat(builder.input(:body))
179
+ end)
180
+ output_buffer.should have_tag("form label", /Elaborate/)
181
+ end
182
+ end
183
+
184
+ it 'should be able to translate nested helper label as Rails does' do
185
+ with_config :i18n_lookups_by_default, true do
186
+ concat(semantic_form_for(@new_post) do |builder|
187
+ concat(builder.inputs(:for => :author) do |f|
188
+ concat(f.input(:login))
189
+ end)
190
+ end)
191
+ output_buffer.should have_tag("form label", /Hello login/)
192
+ end
193
+ end
194
+
195
+ # TODO: Add spec for namespaced models?
196
+
197
+ end
198
+
199
+ end
@@ -0,0 +1,184 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'boolean input' 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.input(:allow_comments, :as => :boolean))
14
+ end)
15
+ end
16
+
17
+ it_should_have_input_wrapper_with_class("boolean")
18
+ it_should_have_input_wrapper_with_class(:input)
19
+ it_should_have_input_wrapper_with_id("post_allow_comments_input")
20
+ it_should_apply_error_logic_for_input_type(:boolean)
21
+
22
+ it 'should generate a label containing the input' do
23
+ output_buffer.should_not have_tag('label.label')
24
+
25
+
26
+ output_buffer.should have_tag('form li label', :count => 1)
27
+ output_buffer.should have_tag('form li label[@for="post_allow_comments"]')
28
+ output_buffer.should have_tag('form li label', /Allow comments/)
29
+ output_buffer.should have_tag('form li label input[@type="checkbox"]', :count => 1)
30
+ output_buffer.should have_tag('form li input[@type="hidden"]', :count => 1)
31
+ output_buffer.should_not have_tag('form li label input[@type="hidden"]', :count => 1) # invalid HTML5
32
+ end
33
+
34
+ it 'should generate a checkbox input' do
35
+ output_buffer.should have_tag('form li label input')
36
+ output_buffer.should have_tag('form li label input#post_allow_comments')
37
+ output_buffer.should have_tag('form li label input[@type="checkbox"]')
38
+ output_buffer.should have_tag('form li label input[@name="post[allow_comments]"]')
39
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="1"]')
40
+ end
41
+
42
+ it 'should generate a checked input if object.method returns true' do
43
+ output_buffer.should have_tag('form li label input[@checked="checked"]')
44
+ output_buffer.should have_tag('form li input[@name="post[allow_comments]"]', :count => 2)
45
+ output_buffer.should have_tag('form li input#post_allow_comments', :count => 1)
46
+ end
47
+
48
+ it 'should generate a checked input if :input_html is passed :checked => checked' do
49
+ concat(semantic_form_for(@new_post) do |builder|
50
+ concat(builder.input(:answer_comments, :as => :boolean, :input_html => {:checked => 'checked'}))
51
+ end)
52
+ output_buffer.should have_tag('form li label input[@checked="checked"]')
53
+ end
54
+
55
+ it 'should name the hidden input with the :name html_option' do
56
+ concat(semantic_form_for(@new_post) do |builder|
57
+ concat(builder.input(:answer_comments, :as => :boolean, :input_html => { :name => "foo" }))
58
+ end)
59
+
60
+ output_buffer.should have_tag('form li input[@type="checkbox"][@name="foo"]', :count => 1)
61
+ output_buffer.should have_tag('form li input[@type="hidden"][@name="foo"]', :count => 1)
62
+ end
63
+
64
+ it 'should name the hidden input with the :name html_option' do
65
+ concat(semantic_form_for(@new_post) do |builder|
66
+ concat(builder.input(:answer_comments, :as => :boolean, :input_html => { :name => "foo" }))
67
+ end)
68
+
69
+ output_buffer.should have_tag('form li input[@type="checkbox"][@name="foo"]', :count => 1)
70
+ output_buffer.should have_tag('form li input[@type="hidden"][@name="foo"]', :count => 1)
71
+ end
72
+
73
+ it "should generate a disabled input and hidden input if :input_html is passed :disabled => 'disabled' " do
74
+ concat(semantic_form_for(@new_post) do |builder|
75
+ concat(builder.input(:allow_comments, :as => :boolean, :input_html => {:disabled => 'disabled'}))
76
+ end)
77
+ output_buffer.should have_tag('form li label input[@disabled="disabled"]', :count => 1)
78
+ output_buffer.should have_tag('form li input[@type="hidden"][@disabled="disabled"]', :count => 1)
79
+ end
80
+
81
+ it 'should generate an input[id] with matching label[for] when id passed in :input_html' do
82
+ concat(semantic_form_for(@new_post) do |builder|
83
+ concat(builder.input(:allow_comments, :as => :boolean, :input_html => {:id => 'custom_id'}))
84
+ end)
85
+ output_buffer.should have_tag('form li label input[@id="custom_id"]')
86
+ output_buffer.should have_tag('form li label[@for="custom_id"]')
87
+ end
88
+
89
+ it 'should allow checked and unchecked values to be sent' do
90
+ concat(semantic_form_for(@new_post) do |builder|
91
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'checked', :unchecked_value => 'unchecked'))
92
+ end)
93
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="checked"]:not([@unchecked_value][@checked_value])')
94
+ output_buffer.should have_tag('form li input[@type="hidden"][@value="unchecked"]')
95
+ output_buffer.should_not have_tag('form li label input[@type="hidden"]') # invalid HTML5
96
+ end
97
+
98
+ it 'should generate a checked input if object.method returns checked value' do
99
+ @new_post.stub!(:allow_comments).and_return('yes')
100
+
101
+ concat(semantic_form_for(@new_post) do |builder|
102
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
103
+ end)
104
+
105
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"][@checked="checked"]')
106
+ end
107
+
108
+ it 'should not generate a checked input if object.method returns unchecked value' do
109
+ @new_post.stub!(:allow_comments).and_return('no')
110
+
111
+ concat(semantic_form_for(@new_post) do |builder|
112
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
113
+ end)
114
+
115
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"]:not([@checked])')
116
+ end
117
+
118
+ it 'should generate a checked input if object.method returns checked value' do
119
+ @new_post.stub!(:allow_comments).and_return('yes')
120
+
121
+ concat(semantic_form_for(@new_post) do |builder|
122
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
123
+ end)
124
+
125
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"][@checked="checked"]')
126
+ end
127
+
128
+ it 'should not generate a checked input if object.method returns unchecked value' do
129
+ @new_post.stub!(:allow_comments).and_return('no')
130
+
131
+ concat(semantic_form_for(@new_post) do |builder|
132
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
133
+ end)
134
+
135
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"]:not([@checked])')
136
+ end
137
+
138
+ it 'should generate a label and a checkbox even if no object is given' do
139
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
140
+ concat(builder.input(:allow_comments, :as => :boolean))
141
+ end)
142
+
143
+ output_buffer.should have_tag('form li label[@for="project_allow_comments"]')
144
+ output_buffer.should have_tag('form li label', /Allow comments/)
145
+ output_buffer.should have_tag('form li label input[@type="checkbox"]')
146
+
147
+ output_buffer.should have_tag('form li label input#project_allow_comments')
148
+ output_buffer.should have_tag('form li label input[@type="checkbox"]')
149
+ output_buffer.should have_tag('form li label input[@name="project[allow_comments]"]')
150
+ end
151
+
152
+ context "when required" do
153
+ it "should add the required attribute to the input's html options" do
154
+ concat(semantic_form_for(@new_post) do |builder|
155
+ concat(builder.input(:title, :as => :boolean, :required => true))
156
+ end)
157
+ output_buffer.should have_tag("input[@required]")
158
+ end
159
+
160
+ it "should not add the required attribute to the boolean fields input's html options" do
161
+ concat(semantic_form_for(@new_post) do |builder|
162
+ concat(builder.input(:title, :as => :boolean))
163
+ end)
164
+ output_buffer.should_not have_tag("input[@required]")
165
+ end
166
+ end
167
+
168
+ describe "when namespace is provided" do
169
+
170
+ before do
171
+ @output_buffer = ''
172
+ mock_everything
173
+
174
+ concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
175
+ concat(builder.input(:allow_comments, :as => :boolean))
176
+ end)
177
+ end
178
+
179
+ it_should_have_input_wrapper_with_id("context2_post_allow_comments_input")
180
+ it_should_have_an_inline_label_for("context2_post_allow_comments")
181
+
182
+ end
183
+
184
+ end