speedo-formstrap 1.2.0

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 (89) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +13 -0
  4. data/Gemfile.lock +117 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +192 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/formtastic-bootstrap.gemspec +56 -0
  10. data/lib/action_view/helpers/text_field_date_helper.rb +166 -0
  11. data/lib/formtastic-bootstrap.rb +7 -0
  12. data/lib/formtastic-bootstrap/actions.rb +4 -0
  13. data/lib/formtastic-bootstrap/actions/base.rb +18 -0
  14. data/lib/formtastic-bootstrap/actions/button_action.rb +7 -0
  15. data/lib/formtastic-bootstrap/actions/input_action.rb +7 -0
  16. data/lib/formtastic-bootstrap/actions/link_action.rb +7 -0
  17. data/lib/formtastic-bootstrap/engine.rb +4 -0
  18. data/lib/formtastic-bootstrap/form_builder.rb +40 -0
  19. data/lib/formtastic-bootstrap/helpers.rb +21 -0
  20. data/lib/formtastic-bootstrap/helpers/action_helper.rb +12 -0
  21. data/lib/formtastic-bootstrap/helpers/actions_helper.rb +23 -0
  22. data/lib/formtastic-bootstrap/helpers/buttons_helper.rb +56 -0
  23. data/lib/formtastic-bootstrap/helpers/fieldset_wrapper.rb +42 -0
  24. data/lib/formtastic-bootstrap/helpers/input_helper.rb +12 -0
  25. data/lib/formtastic-bootstrap/helpers/inputs_helper.rb +36 -0
  26. data/lib/formtastic-bootstrap/inputs.rb +29 -0
  27. data/lib/formtastic-bootstrap/inputs/base.rb +23 -0
  28. data/lib/formtastic-bootstrap/inputs/base/choices.rb +38 -0
  29. data/lib/formtastic-bootstrap/inputs/base/errors.rb +48 -0
  30. data/lib/formtastic-bootstrap/inputs/base/hints.rb +27 -0
  31. data/lib/formtastic-bootstrap/inputs/base/html.rb +21 -0
  32. data/lib/formtastic-bootstrap/inputs/base/labelling.rb +28 -0
  33. data/lib/formtastic-bootstrap/inputs/base/numeric.rb +18 -0
  34. data/lib/formtastic-bootstrap/inputs/base/stringish.rb +18 -0
  35. data/lib/formtastic-bootstrap/inputs/base/timeish.rb +28 -0
  36. data/lib/formtastic-bootstrap/inputs/base/wrapping.rb +74 -0
  37. data/lib/formtastic-bootstrap/inputs/boolean_input.rb +29 -0
  38. data/lib/formtastic-bootstrap/inputs/check_boxes_input.rb +36 -0
  39. data/lib/formtastic-bootstrap/inputs/date_input.rb +16 -0
  40. data/lib/formtastic-bootstrap/inputs/datetime_input.rb +19 -0
  41. data/lib/formtastic-bootstrap/inputs/email_input.rb +15 -0
  42. data/lib/formtastic-bootstrap/inputs/file_input.rb +14 -0
  43. data/lib/formtastic-bootstrap/inputs/hidden_input.rb +14 -0
  44. data/lib/formtastic-bootstrap/inputs/number_input.rb +15 -0
  45. data/lib/formtastic-bootstrap/inputs/password_input.rb +15 -0
  46. data/lib/formtastic-bootstrap/inputs/phone_input.rb +15 -0
  47. data/lib/formtastic-bootstrap/inputs/radio_input.rb +33 -0
  48. data/lib/formtastic-bootstrap/inputs/range_input.rb +15 -0
  49. data/lib/formtastic-bootstrap/inputs/search_input.rb +15 -0
  50. data/lib/formtastic-bootstrap/inputs/select_input.rb +14 -0
  51. data/lib/formtastic-bootstrap/inputs/string_input.rb +15 -0
  52. data/lib/formtastic-bootstrap/inputs/text_input.rb +14 -0
  53. data/lib/formtastic-bootstrap/inputs/time_input.rb +16 -0
  54. data/lib/formtastic-bootstrap/inputs/time_zone_input.rb +14 -0
  55. data/lib/formtastic-bootstrap/inputs/url_input.rb +14 -0
  56. data/spec/actions/button_action_spec.rb +68 -0
  57. data/spec/actions/generic_action_spec.rb +486 -0
  58. data/spec/actions/input_action_spec.rb +64 -0
  59. data/spec/actions/link_action_spec.rb +93 -0
  60. data/spec/builder/semantic_fields_for_spec.rb +130 -0
  61. data/spec/helpers/action_helper_spec.rb +365 -0
  62. data/spec/helpers/actions_helper_spec.rb +143 -0
  63. data/spec/helpers/buttons_helper_spec.rb +159 -0
  64. data/spec/helpers/input_helper_spec.rb +956 -0
  65. data/spec/helpers/inputs_helper_spec.rb +591 -0
  66. data/spec/inputs/boolean_input_spec.rb +221 -0
  67. data/spec/inputs/check_boxes_input_spec.rb +467 -0
  68. data/spec/inputs/date_input_spec.rb +213 -0
  69. data/spec/inputs/datetime_input_spec.rb +101 -0
  70. data/spec/inputs/email_input_spec.rb +87 -0
  71. data/spec/inputs/file_input_spec.rb +91 -0
  72. data/spec/inputs/hidden_input_spec.rb +150 -0
  73. data/spec/inputs/number_input_spec.rb +817 -0
  74. data/spec/inputs/password_input_spec.rb +101 -0
  75. data/spec/inputs/phone_input_spec.rb +87 -0
  76. data/spec/inputs/radio_input_spec.rb +268 -0
  77. data/spec/inputs/range_input_spec.rb +507 -0
  78. data/spec/inputs/search_input_spec.rb +86 -0
  79. data/spec/inputs/select_input_spec.rb +613 -0
  80. data/spec/inputs/string_input_spec.rb +227 -0
  81. data/spec/inputs/text_input_spec.rb +190 -0
  82. data/spec/inputs/time_input_spec.rb +206 -0
  83. data/spec/inputs/time_zone_input_spec.rb +120 -0
  84. data/spec/inputs/url_input_spec.rb +87 -0
  85. data/spec/spec_helper.rb +24 -0
  86. data/spec/support/custom_macros.rb +575 -0
  87. data/spec/support/depracation.rb +6 -0
  88. data/spec/support/formtastic_spec_helper.rb +398 -0
  89. metadata +216 -0
@@ -0,0 +1,221 @@
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
+ Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
12
+
13
+ concat(semantic_form_for(@new_post) do |builder|
14
+ concat(builder.input(:allow_comments, :as => :boolean))
15
+ end)
16
+ end
17
+
18
+ it_should_have_input_wrapper_with_class("boolean-wrapper")
19
+ it_should_have_input_wrapper_with_class("control-group")
20
+ it_should_have_input_class_in_the_right_place
21
+ it_should_have_input_wrapper_with_id("post_allow_comments_input")
22
+ it_should_apply_error_logic_for_input_type(:boolean, :block)
23
+
24
+ it 'should generate a label containing the input' do
25
+ output_buffer.should have_tag('label.control-label')
26
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox', :count => 1)
27
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox[@for="post_allow_comments"]')
28
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox', /Allow comments/)
29
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input[@type="checkbox"]', :count => 1)
30
+ output_buffer.should have_tag('form div.control-group input[@type="hidden"]', :count => 1)
31
+ output_buffer.should_not have_tag('form div.control-group 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 div.control-group div.controls label.checkbox input')
36
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input#post_allow_comments')
37
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input[@type="checkbox"]')
38
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input[@name="post[allow_comments]"]')
39
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox 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 div.control-group div.controls label.checkbox input[@checked="checked"]')
44
+ output_buffer.should have_tag('form div.control-group input[@name="post[allow_comments]"]', :count => 2)
45
+ output_buffer.should have_tag('form div.control-group div.controls 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 div.control-group div.controls label.checkbox 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 div.control-group div.controls input[@type="checkbox"][@name="foo"]', :count => 1)
61
+ output_buffer.should have_tag('form div.control-group 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 div.control-group div.controls input[@type="checkbox"][@name="foo"]', :count => 1)
70
+ output_buffer.should have_tag('form div.control-group 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 div.control-group div.controls label input[@disabled="disabled"]', :count => 1)
78
+ output_buffer.should have_tag('form div.control-group 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 div.control-group div.controls label.checkbox input[@id="custom_id"]')
86
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox[@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 div.control-group div.controls label.checkbox input[@type="checkbox"][@value="checked"]:not([@unchecked_value][@checked_value])')
94
+ output_buffer.should have_tag('form div.control-group input[@type="hidden"][@value="unchecked"]')
95
+ output_buffer.should_not have_tag('form div.control-group label.checkbox 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 label.checkbox 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 div.control-group div.controls label.checkbox 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 div.control-group div.controls label.checkbox 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 div.control-group div.controls label.checkbox 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 div.control-group div.controls label.checkbox[@for="project_allow_comments"]')
144
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox', /Allow comments/)
145
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input[@type="checkbox"]')
146
+
147
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input#project_allow_comments')
148
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input[@type="checkbox"]')
149
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input[@name="project[allow_comments]"]')
150
+ end
151
+
152
+ context "when required" do
153
+
154
+ it "should add the required attribute to the input's html options" do
155
+ with_config :use_required_attribute, true do
156
+ concat(semantic_form_for(@new_post) do |builder|
157
+ concat(builder.input(:title, :as => :boolean, :required => true))
158
+ end)
159
+ output_buffer.should have_tag("input[@required]")
160
+ end
161
+ end
162
+
163
+ it "should not add the required attribute to the boolean fields input's html options" do
164
+ with_config :use_required_attribute, true do
165
+ concat(semantic_form_for(@new_post) do |builder|
166
+ concat(builder.input(:title, :as => :boolean))
167
+ end)
168
+ output_buffer.should_not have_tag("input[@required]")
169
+ end
170
+ end
171
+
172
+ end
173
+
174
+ describe "when namespace is provided" do
175
+
176
+ before do
177
+ @output_buffer = ''
178
+ mock_everything
179
+ Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
180
+
181
+ concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
182
+ concat(builder.input(:allow_comments, :as => :boolean))
183
+ end)
184
+ end
185
+
186
+ it_should_have_input_wrapper_with_id("context2_post_allow_comments_input")
187
+ it_should_have_an_inline_label_for("context2_post_allow_comments")
188
+
189
+ end
190
+
191
+ describe "when index is provided" do
192
+
193
+ before do
194
+ @output_bugger = ''
195
+ mock_everything
196
+
197
+ concat(semantic_form_for(@new_post) do |builder|
198
+ concat(builder.fields_for(:author, :index => 3) do |author|
199
+ concat(author.input(:name, :as => :boolean))
200
+ end)
201
+ end)
202
+ end
203
+
204
+ it 'should index the id of the wrapper' do
205
+ output_buffer.should have_tag("div#post_author_attributes_3_name_input")
206
+ end
207
+
208
+ it 'should index the id of the input tag' do
209
+ output_buffer.should have_tag("input#post_author_attributes_3_name")
210
+ end
211
+
212
+ it 'should index the name of the hidden input' do
213
+ output_buffer.should have_tag("input[@type='hidden'][@name='post[author_attributes][3][name]']")
214
+ end
215
+
216
+ it 'should index the name of the checkbox input' do
217
+ output_buffer.should have_tag("input[@type='checkbox'][@name='post[author_attributes][3][name]']")
218
+ end
219
+ end
220
+
221
+ end
@@ -0,0 +1,467 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'check_boxes input' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ describe 'for a has_many association' do
9
+ before do
10
+ @output_buffer = ''
11
+ mock_everything
12
+ Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
13
+
14
+ concat(semantic_form_for(@fred) do |builder|
15
+ concat(builder.input(:posts, :as => :check_boxes, :value_as_class => true, :required => true))
16
+ end)
17
+ end
18
+
19
+ it_should_have_input_wrapper_with_class("check_boxes-wrapper")
20
+ it_should_have_input_wrapper_with_class("control-group")
21
+ it_should_have_input_class_in_the_right_place
22
+ it_should_have_input_wrapper_with_id("author_posts_input")
23
+ it_should_have_a_nested_div
24
+ it_should_have_a_nested_div_with_class('choices.controls')
25
+ #it_should_have_a_nested_unordered_list_with_class('choices-group.inputs-list')
26
+ it_should_apply_error_logic_for_input_type(:check_boxes, :block)
27
+ it_should_call_find_on_association_class_when_no_collection_is_provided(:check_boxes)
28
+ it_should_use_the_collection_when_provided(:check_boxes, 'input[@type="checkbox"]')
29
+
30
+ # TODO Refactor out the next three tests and their bretheren in radio_input_spec
31
+ it 'should generate a \'legend\' containing a label with text for the input' do
32
+ output_buffer.should have_tag('form div.control-group label.control-label')
33
+ output_buffer.should have_tag('form div.control-group label.control-label', /Posts/)
34
+ end
35
+
36
+ it 'should not link the \'legend\' label to any input' do
37
+ output_buffer.should_not have_tag('form div.control-group > label.control-label[@for]')
38
+ end
39
+
40
+ # it 'should generate an unordered list with a list item for each choice' do
41
+ # output_buffer.should have_tag('form div.control-group div.controls ul')
42
+ # output_buffer.should have_tag('form div.control-group div.controls ul li.choice', :count => ::Post.all.size)
43
+ # end
44
+
45
+ # it 'should generate a legend containing a label with text for the input' do
46
+ # output_buffer.should have_tag('form li fieldset legend.label label')
47
+ # output_buffer.should have_tag('form li fieldset legend.label label', /Posts/)
48
+ # end
49
+ #
50
+ # it 'should not link the label within the legend to any input' do
51
+ # output_buffer.should_not have_tag('form li fieldset legend label[@for^="author_post_ids_"]')
52
+ # end
53
+ #
54
+ # it 'should generate an ordered list with an li.choice for each choice' do
55
+ # output_buffer.should have_tag('form li fieldset ol')
56
+ # output_buffer.should have_tag('form li fieldset ol li.choice input[@type=checkbox]', :count => ::Post.all.size)
57
+ # end
58
+
59
+ it 'should have one option with a "checked" attribute' do
60
+ output_buffer.should have_tag('form .controls input[@checked]', :count => 1)
61
+ end
62
+
63
+ it 'should not generate hidden inputs with default value blank' do
64
+ output_buffer.should_not have_tag("form div div label input[@type='hidden'][@value='']")
65
+ end
66
+
67
+ # it 'should not render hidden inputs inside the ol' do
68
+ # output_buffer.should_not have_tag("form div div ul li input[@type='hidden']")
69
+ # end
70
+
71
+ it 'should render one hidden input for each choice outside the ol' do
72
+ output_buffer.should have_tag("form div.control-group > input[@type='hidden']", :count => 1)
73
+ end
74
+
75
+ describe "each choice" do
76
+
77
+ it 'should not give the choice label the .control-label class' do
78
+ output_buffer.should_not have_tag('div.controls label.control-label')
79
+ end
80
+
81
+ it 'should not be marked as required' do
82
+ output_buffer.should_not have_tag('div.checkbox input[@required]')
83
+ end
84
+
85
+ it 'should contain a label for the radio input with a nested input and label text' do
86
+ ::Post.all.each do |post|
87
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox', /#{post.to_label}/)
88
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox[@for='author_post_ids_#{post.id}']")
89
+ end
90
+ end
91
+
92
+ it 'should use values as li.class when value_as_class is true' do
93
+ ::Post.all.each do |post|
94
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox.post_#{post.id}")
95
+ end
96
+ end
97
+
98
+ it 'should have a checkbox input but no hidden field for each post' do
99
+ ::Post.all.each do |post|
100
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input#author_post_ids_#{post.id}")
101
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@name='author[post_ids][]']", :count => 1)
102
+ end
103
+ end
104
+
105
+ it 'should have a hidden field with an empty array value for the collection to allow clearing of all checkboxes' do
106
+ output_buffer.should have_tag("form div.control-group > input[@type=hidden][@name='author[post_ids][]'][@value='']", :count => 1)
107
+ end
108
+
109
+ it 'the hidden field with an empty array value should be followed by the div.controls and the ul' do
110
+ output_buffer.should have_tag("form div.control-group > input[@type=hidden][@name='author[post_ids][]'][@value=''] + div.controls", :count => 1)
111
+ end
112
+
113
+ it 'should not have a hidden field with an empty string value for the collection' do
114
+ output_buffer.should_not have_tag("form div.control-group > input[@type=hidden][@name='author[post_ids]'][@value='']", :count => 1)
115
+ end
116
+
117
+ it 'should have a checkbox and a hidden field for each post with :hidden_field => true' do
118
+ output_buffer.replace ''
119
+
120
+ concat(semantic_form_for(@fred) do |builder|
121
+ concat(builder.input(:posts, :as => :check_boxes, :hidden_fields => true, :value_as_class => true))
122
+ end)
123
+
124
+ ::Post.all.each do |post|
125
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input#author_post_ids_#{post.id}")
126
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@name='author[post_ids][]']", :count => 2)
127
+ end
128
+
129
+ end
130
+
131
+ it "should mark input as checked if it's the the existing choice" do
132
+ ::Post.all.include?(@fred.posts.first).should be_true
133
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@checked='checked']")
134
+ end
135
+ end
136
+
137
+ describe 'and no object is given' do
138
+ before(:each) do
139
+ output_buffer.replace ''
140
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
141
+ concat(builder.input(:author_id, :as => :check_boxes, :collection => ::Author.all))
142
+ end)
143
+ end
144
+
145
+ it 'should generate a top-level div with \'legend\'' do
146
+ output_buffer.should have_tag('form div.control-group > label.control-label', /Author/)
147
+ end
148
+
149
+ it 'shold generate an li tag for each item in the collection' do
150
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox input[@type=checkbox]', :count => ::Author.all.size)
151
+ end
152
+
153
+ it 'should generate labels for each item' do
154
+ ::Author.all.each do |author|
155
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox', /#{author.to_label}/)
156
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox[@for='project_author_id_#{author.id}']")
157
+ end
158
+ end
159
+
160
+ it 'should generate inputs for each item' do
161
+ ::Author.all.each do |author|
162
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input#project_author_id_#{author.id}")
163
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@type='checkbox']")
164
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@value='#{author.id}']")
165
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@name='project[author_id][]']")
166
+ end
167
+ end
168
+
169
+ it 'should html escape the label string' do
170
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
171
+ concat(builder.input(:author_id, :as => :check_boxes, :collection => [["<b>Item 1</b>", 1], ["<b>Item 2</b>", 2]]))
172
+ end)
173
+
174
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox') do |label|
175
+ # label.body.should match /&lt;b&gt;Item [12]&lt;\/b&gt;$/
176
+ label.body.should match /&lt;b&gt;Item [12]&lt;\/b&gt;/
177
+ end
178
+ end
179
+ end
180
+
181
+ describe 'when :hidden_fields is set to false' do
182
+ before do
183
+ @output_buffer = ''
184
+ mock_everything
185
+
186
+ concat(semantic_form_for(@fred) do |builder|
187
+ concat(builder.input(:posts, :as => :check_boxes, :value_as_class => true, :hidden_fields => false))
188
+ end)
189
+ end
190
+
191
+ it 'should have a checkbox input for each post' do
192
+ ::Post.all.each do |post|
193
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input#author_post_ids_#{post.id}")
194
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@name='author[post_ids][]']", :count => ::Post.all.length)
195
+ end
196
+ end
197
+
198
+ it "should mark input as checked if it's the the existing choice" do
199
+ ::Post.all.include?(@fred.posts.first).should be_true
200
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@checked='checked']")
201
+ end
202
+
203
+ it 'should not generate empty hidden inputs' do
204
+ output_buffer.should_not have_tag("form div.control-group div.controls label.checkbox input[@type='hidden'][@value='']", :count => ::Post.all.length)
205
+ end
206
+ end
207
+
208
+ describe 'when :disabled is set' do
209
+ before do
210
+ @output_buffer = ''
211
+ end
212
+
213
+ describe "no disabled items" do
214
+ before do
215
+ @new_post.stub!(:author_ids).and_return(nil)
216
+
217
+ concat(semantic_form_for(@new_post) do |builder|
218
+ concat(builder.input(:authors, :as => :check_boxes, :disabled => nil))
219
+ end)
220
+ end
221
+
222
+ it 'should not have any disabled item(s)' do
223
+ output_buffer.should_not have_tag("form div.control-group div.controls label.checkbox input[@disabled='disabled']")
224
+ end
225
+ end
226
+
227
+ describe "single disabled item" do
228
+ before do
229
+ @new_post.stub!(:author_ids).and_return(nil)
230
+
231
+ concat(semantic_form_for(@new_post) do |builder|
232
+ concat(builder.input(:authors, :as => :check_boxes, :disabled => @fred.id))
233
+ end)
234
+ end
235
+
236
+ it "should have one item disabled; the specified one" do
237
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@disabled='disabled']", :count => 1)
238
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox[@for='post_author_ids_#{@fred.id}']", /fred/i)
239
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@disabled='disabled'][@value='#{@fred.id}']")
240
+ end
241
+ end
242
+
243
+ describe "multiple disabled items" do
244
+ before do
245
+ @new_post.stub!(:author_ids).and_return(nil)
246
+
247
+ concat(semantic_form_for(@new_post) do |builder|
248
+ concat(builder.input(:authors, :as => :check_boxes, :disabled => [@bob.id, @fred.id]))
249
+ end)
250
+ end
251
+
252
+ it "should have multiple items disabled; the specified ones" do
253
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@disabled='disabled']", :count => 2)
254
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox[@for='post_author_ids_#{@bob.id}']", /bob/i)
255
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@disabled='disabled'][@value='#{@bob.id}']")
256
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox[@for='post_author_ids_#{@fred.id}']", /fred/i)
257
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@disabled='disabled'][@value='#{@fred.id}']")
258
+ end
259
+ end
260
+
261
+ end
262
+
263
+ describe "with i18n of the legend label" do
264
+
265
+ before do
266
+ ::I18n.backend.store_translations :en, :formtastic => { :labels => { :post => { :authors => "Translated!" }}}
267
+ with_config :i18n_lookups_by_default, true do
268
+ @new_post.stub!(:author_ids).and_return(nil)
269
+ concat(semantic_form_for(@new_post) do |builder|
270
+ concat(builder.input(:authors, :as => :check_boxes))
271
+ end)
272
+ end
273
+ end
274
+
275
+ after do
276
+ ::I18n.backend.reload!
277
+ end
278
+
279
+ it "should do foo" do
280
+ output_buffer.should have_tag("div.control-group > label.control-label", /Translated/)
281
+ end
282
+
283
+ end
284
+
285
+ describe "when :label option is set" do
286
+ before do
287
+ @new_post.stub!(:author_ids).and_return(nil)
288
+ concat(semantic_form_for(@new_post) do |builder|
289
+ concat(builder.input(:authors, :as => :check_boxes, :label => 'The authors'))
290
+ end)
291
+ end
292
+
293
+ it "should output the correct label title" do
294
+ output_buffer.should have_tag("div.control-group > label.control-label", /The authors/)
295
+ end
296
+ end
297
+
298
+ describe "when :label option is false" do
299
+ before do
300
+ @output_buffer = ''
301
+ @new_post.stub!(:author_ids).and_return(nil)
302
+ concat(semantic_form_for(@new_post) do |builder|
303
+ concat(builder.input(:authors, :as => :check_boxes, :label => false))
304
+ end)
305
+ end
306
+
307
+ it "should output an empty \'legend\'" do
308
+ output_buffer.should have_tag("div.control-group > label.control-label", "")
309
+ end
310
+
311
+ it "should not cause escaped HTML" do
312
+ output_buffer.should_not include("&gt;")
313
+ end
314
+
315
+ end
316
+
317
+ describe "when :required option is true" do
318
+ before do
319
+ @new_post.stub!(:author_ids).and_return(nil)
320
+ concat(semantic_form_for(@new_post) do |builder|
321
+ concat(builder.input(:authors, :as => :check_boxes, :required => true))
322
+ end)
323
+ end
324
+
325
+ it "should output the correct label title" do
326
+ output_buffer.should have_tag("div.control-group > label.control-label abbr")
327
+ end
328
+ end
329
+
330
+ end
331
+
332
+ describe 'for a has_and_belongs_to_many association' do
333
+
334
+ before do
335
+ @output_buffer = ''
336
+ mock_everything
337
+
338
+ concat(semantic_form_for(@freds_post) do |builder|
339
+ concat(builder.input(:authors, :as => :check_boxes))
340
+ end)
341
+ end
342
+
343
+ it 'should render checkboxes' do
344
+ # I'm aware these two lines test the same thing
345
+ output_buffer.should have_tag('input[type="checkbox"]', :count => 2)
346
+ output_buffer.should have_tag('input[type="checkbox"]', :count => ::Author.all.size)
347
+ end
348
+
349
+ it 'should only select checkboxes that are present in the association' do
350
+ # I'm aware these two lines test the same thing
351
+ output_buffer.should have_tag('input[checked="checked"]', :count => 1)
352
+ output_buffer.should have_tag('input[checked="checked"]', :count => @freds_post.authors.size)
353
+ end
354
+
355
+ end
356
+
357
+ describe 'for an association when a :collection is provided' do
358
+ describe 'it should use the specified :member_value option' do
359
+ before do
360
+ @output_buffer = ''
361
+ mock_everything
362
+ end
363
+
364
+ it 'to set the right input value' do
365
+ item = mock('item')
366
+ item.should_not_receive(:id)
367
+ item.stub!(:custom_value).and_return('custom_value')
368
+ item.should_receive(:custom_value).exactly(3).times
369
+ @new_post.author.should_receive(:custom_value).exactly(1).times
370
+ concat(semantic_form_for(@new_post) do |builder|
371
+ concat(builder.input(:author, :as => :check_boxes, :member_value => :custom_value, :collection => [item, item, item]))
372
+ end)
373
+ output_buffer.should have_tag('input[@type=checkbox][@value="custom_value"]', :count => 3)
374
+ end
375
+ end
376
+ end
377
+
378
+ describe 'when :collection is provided as an array of arrays' do
379
+ before do
380
+ @output_buffer = ''
381
+ mock_everything
382
+ @fred.stub(:genres) { ['fiction', 'biography'] }
383
+
384
+ concat(semantic_form_for(@fred) do |builder|
385
+ concat(builder.input(:genres, :as => :check_boxes, :collection => [['Fiction', 'fiction'], ['Non-fiction', 'non_fiction'], ['Biography', 'biography']]))
386
+ end)
387
+ end
388
+
389
+ it 'should check the correct checkboxes' do
390
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@value='fiction'][@checked='checked']")
391
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox input[@value='biography'][@checked='checked']")
392
+ end
393
+ end
394
+
395
+ describe "when namespace is provided" do
396
+
397
+ before do
398
+ @output_buffer = ''
399
+ mock_everything
400
+
401
+ concat(semantic_form_for(@fred, :namespace => "context2") do |builder|
402
+ concat(builder.input(:posts, :as => :check_boxes))
403
+ end)
404
+ end
405
+
406
+ it "should have a label for #context2_author_post_ids_19" do
407
+ output_buffer.should have_tag("form label.checkbox[@for='context2_author_post_ids_19']")
408
+ end
409
+
410
+ it_should_have_input_with_id('context2_author_post_ids_19')
411
+ it_should_have_input_wrapper_with_id("context2_author_posts_input")
412
+ end
413
+
414
+ describe "when index is provided" do
415
+
416
+ before do
417
+ @output_buffer = ''
418
+ mock_everything
419
+
420
+ concat(semantic_form_for(@fred) do |builder|
421
+ concat(builder.fields_for(@fred.posts.first, :index => 3) do |author|
422
+ concat(author.input(:authors, :as => :check_boxes))
423
+ end)
424
+ end)
425
+ end
426
+
427
+ it 'should index the id of the wrapper' do
428
+ output_buffer.should have_tag("div#author_post_3_authors_input")
429
+ end
430
+
431
+ it 'should index the id of the input tag' do
432
+ output_buffer.should have_tag("input#author_post_3_author_ids_42")
433
+ end
434
+
435
+ it 'should index the name of the checkbox input' do
436
+ output_buffer.should have_tag("input[@type='checkbox'][@name='author[post][3][author_ids][]']")
437
+ end
438
+
439
+ end
440
+
441
+
442
+ describe "when collection is an array" do
443
+ before do
444
+ @output_buffer = ''
445
+ @_collection = [["First", 1], ["Second", 2]]
446
+ mock_everything
447
+ Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
448
+
449
+ concat(semantic_form_for(@fred) do |builder|
450
+ concat(builder.input(:posts, :as => :check_boxes, :collection => @_collection))
451
+ end)
452
+ end
453
+
454
+ it "should use array items for labels and values" do
455
+ @_collection.each do |post|
456
+ output_buffer.should have_tag('form div.control-group div.controls label.checkbox', /#{post.first}/)
457
+ output_buffer.should have_tag("form div.control-group div.controls label.checkbox[@for='author_post_ids_#{post.last}']")
458
+ end
459
+ end
460
+
461
+ it "should not check any items" do
462
+ output_buffer.should have_tag('form li input[@checked]', :count => 0)
463
+ end
464
+ end
465
+
466
+ end
467
+