formtastic-bootstrap 1.0.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 (72) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +123 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +159 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/formtastic-bootstrap.gemspec +128 -0
  10. data/lib/action_view/helpers/text_field_date_helper.rb +166 -0
  11. data/lib/formtastic-bootstrap.rb +5 -0
  12. data/lib/formtastic-bootstrap/form_builder.rb +38 -0
  13. data/lib/formtastic-bootstrap/helpers.rb +19 -0
  14. data/lib/formtastic-bootstrap/helpers/buttons_helper.rb +47 -0
  15. data/lib/formtastic-bootstrap/helpers/fieldset_wrapper.rb +37 -0
  16. data/lib/formtastic-bootstrap/helpers/input_helper.rb +12 -0
  17. data/lib/formtastic-bootstrap/helpers/inputs_helper.rb +36 -0
  18. data/lib/formtastic-bootstrap/inputs.rb +28 -0
  19. data/lib/formtastic-bootstrap/inputs/base.rb +22 -0
  20. data/lib/formtastic-bootstrap/inputs/base/choices.rb +49 -0
  21. data/lib/formtastic-bootstrap/inputs/base/errors.rb +48 -0
  22. data/lib/formtastic-bootstrap/inputs/base/hints.rb +27 -0
  23. data/lib/formtastic-bootstrap/inputs/base/html.rb +21 -0
  24. data/lib/formtastic-bootstrap/inputs/base/labelling.rb +18 -0
  25. data/lib/formtastic-bootstrap/inputs/base/stringish.rb +18 -0
  26. data/lib/formtastic-bootstrap/inputs/base/timeish.rb +35 -0
  27. data/lib/formtastic-bootstrap/inputs/base/wrapping.rb +56 -0
  28. data/lib/formtastic-bootstrap/inputs/boolean_input.rb +33 -0
  29. data/lib/formtastic-bootstrap/inputs/check_boxes_input.rb +35 -0
  30. data/lib/formtastic-bootstrap/inputs/date_input.rb +16 -0
  31. data/lib/formtastic-bootstrap/inputs/datetime_input.rb +19 -0
  32. data/lib/formtastic-bootstrap/inputs/email_input.rb +15 -0
  33. data/lib/formtastic-bootstrap/inputs/file_input.rb +14 -0
  34. data/lib/formtastic-bootstrap/inputs/hidden_input.rb +12 -0
  35. data/lib/formtastic-bootstrap/inputs/number_input.rb +15 -0
  36. data/lib/formtastic-bootstrap/inputs/password_input.rb +15 -0
  37. data/lib/formtastic-bootstrap/inputs/phone_input.rb +15 -0
  38. data/lib/formtastic-bootstrap/inputs/radio_input.rb +32 -0
  39. data/lib/formtastic-bootstrap/inputs/range_input.rb +15 -0
  40. data/lib/formtastic-bootstrap/inputs/search_input.rb +15 -0
  41. data/lib/formtastic-bootstrap/inputs/select_input.rb +14 -0
  42. data/lib/formtastic-bootstrap/inputs/string_input.rb +15 -0
  43. data/lib/formtastic-bootstrap/inputs/text_input.rb +14 -0
  44. data/lib/formtastic-bootstrap/inputs/time_input.rb +16 -0
  45. data/lib/formtastic-bootstrap/inputs/url_input.rb +14 -0
  46. data/spec/builder/errors_spec.rb +214 -0
  47. data/spec/builder/semantic_fields_for_spec.rb +130 -0
  48. data/spec/helpers/input_helper_spec.rb +956 -0
  49. data/spec/helpers/inputs_helper_spec.rb +577 -0
  50. data/spec/inputs/boolean_input_spec.rb +193 -0
  51. data/spec/inputs/check_boxes_input_spec.rb +439 -0
  52. data/spec/inputs/date_input_spec.rb +147 -0
  53. data/spec/inputs/datetime_input_spec.rb +101 -0
  54. data/spec/inputs/email_input_spec.rb +59 -0
  55. data/spec/inputs/file_input_spec.rb +63 -0
  56. data/spec/inputs/hidden_input_spec.rb +122 -0
  57. data/spec/inputs/number_input_spec.rb +787 -0
  58. data/spec/inputs/password_input_spec.rb +73 -0
  59. data/spec/inputs/phone_input_spec.rb +59 -0
  60. data/spec/inputs/radio_input_spec.rb +240 -0
  61. data/spec/inputs/range_input_spec.rb +479 -0
  62. data/spec/inputs/search_input_spec.rb +59 -0
  63. data/spec/inputs/select_input_spec.rb +567 -0
  64. data/spec/inputs/string_input_spec.rb +182 -0
  65. data/spec/inputs/text_input_spec.rb +163 -0
  66. data/spec/inputs/time_input_spec.rb +206 -0
  67. data/spec/inputs/url_input_spec.rb +59 -0
  68. data/spec/spec_helper.rb +24 -0
  69. data/spec/support/custom_macros.rb +704 -0
  70. data/spec/support/depracation.rb +6 -0
  71. data/spec/support/formtastic_spec_helper.rb +382 -0
  72. metadata +204 -0
@@ -0,0 +1,193 @@
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")
19
+ it_should_have_input_wrapper_with_class(:clearfix)
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_not have_tag('label.label')
26
+
27
+
28
+ output_buffer.should have_tag('form div.clearfix div.input ul li label', :count => 1)
29
+ output_buffer.should have_tag('form div.clearfix div.input ul li label[@for="post_allow_comments"]')
30
+ output_buffer.should have_tag('form div.clearfix div.input ul li label', /Allow comments/)
31
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"]', :count => 1)
32
+ output_buffer.should have_tag('form div.clearfix input[@type="hidden"]', :count => 1)
33
+ output_buffer.should_not have_tag('form div.clearfix label input[@type="hidden"]', :count => 1) # invalid HTML5
34
+ end
35
+
36
+ it 'should generate a checkbox input' do
37
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input')
38
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input#post_allow_comments')
39
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"]')
40
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@name="post[allow_comments]"]')
41
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"][@value="1"]')
42
+ end
43
+
44
+ it 'should generate a checked input if object.method returns true' do
45
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@checked="checked"]')
46
+ output_buffer.should have_tag('form div.clearfix input[@name="post[allow_comments]"]', :count => 2)
47
+ output_buffer.should have_tag('form div.clearfix div.input ul li input#post_allow_comments', :count => 1)
48
+ end
49
+
50
+ it 'should generate a checked input if :input_html is passed :checked => checked' do
51
+ concat(semantic_form_for(@new_post) do |builder|
52
+ concat(builder.input(:answer_comments, :as => :boolean, :input_html => {:checked => 'checked'}))
53
+ end)
54
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@checked="checked"]')
55
+ end
56
+
57
+ it 'should name the hidden input with the :name html_option' do
58
+ concat(semantic_form_for(@new_post) do |builder|
59
+ concat(builder.input(:answer_comments, :as => :boolean, :input_html => { :name => "foo" }))
60
+ end)
61
+
62
+ output_buffer.should have_tag('form div.clearfix div.input ul li input[@type="checkbox"][@name="foo"]', :count => 1)
63
+ output_buffer.should have_tag('form div.clearfix input[@type="hidden"][@name="foo"]', :count => 1)
64
+ end
65
+
66
+ it 'should name the hidden input with the :name html_option' do
67
+ concat(semantic_form_for(@new_post) do |builder|
68
+ concat(builder.input(:answer_comments, :as => :boolean, :input_html => { :name => "foo" }))
69
+ end)
70
+
71
+ output_buffer.should have_tag('form div.clearfix div.input ul li input[@type="checkbox"][@name="foo"]', :count => 1)
72
+ output_buffer.should have_tag('form div.clearfix input[@type="hidden"][@name="foo"]', :count => 1)
73
+ end
74
+
75
+ it "should generate a disabled input and hidden input if :input_html is passed :disabled => 'disabled' " do
76
+ concat(semantic_form_for(@new_post) do |builder|
77
+ concat(builder.input(:allow_comments, :as => :boolean, :input_html => {:disabled => 'disabled'}))
78
+ end)
79
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@disabled="disabled"]', :count => 1)
80
+ output_buffer.should have_tag('form div.clearfix input[@type="hidden"][@disabled="disabled"]', :count => 1)
81
+ end
82
+
83
+ it 'should generate an input[id] with matching label[for] when id passed in :input_html' do
84
+ concat(semantic_form_for(@new_post) do |builder|
85
+ concat(builder.input(:allow_comments, :as => :boolean, :input_html => {:id => 'custom_id'}))
86
+ end)
87
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@id="custom_id"]')
88
+ output_buffer.should have_tag('form div.clearfix div.input ul li label[@for="custom_id"]')
89
+ end
90
+
91
+ it 'should allow checked and unchecked values to be sent' do
92
+ concat(semantic_form_for(@new_post) do |builder|
93
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'checked', :unchecked_value => 'unchecked'))
94
+ end)
95
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"][@value="checked"]:not([@unchecked_value][@checked_value])')
96
+ output_buffer.should have_tag('form div.clearfix input[@type="hidden"][@value="unchecked"]')
97
+ output_buffer.should_not have_tag('form div.clearfix label input[@type="hidden"]') # invalid HTML5
98
+ end
99
+
100
+ it 'should generate a checked input if object.method returns checked value' do
101
+ @new_post.stub!(:allow_comments).and_return('yes')
102
+
103
+ concat(semantic_form_for(@new_post) do |builder|
104
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
105
+ end)
106
+
107
+ output_buffer.should have_tag('form li label input[@type="checkbox"][@value="yes"][@checked="checked"]')
108
+ end
109
+
110
+ it 'should not generate a checked input if object.method returns unchecked value' do
111
+ @new_post.stub!(:allow_comments).and_return('no')
112
+
113
+ concat(semantic_form_for(@new_post) do |builder|
114
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
115
+ end)
116
+
117
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"][@value="yes"]:not([@checked])')
118
+ end
119
+
120
+ it 'should generate a checked input if object.method returns checked value' do
121
+ @new_post.stub!(:allow_comments).and_return('yes')
122
+
123
+ concat(semantic_form_for(@new_post) do |builder|
124
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
125
+ end)
126
+
127
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"][@value="yes"][@checked="checked"]')
128
+ end
129
+
130
+ it 'should not generate a checked input if object.method returns unchecked value' do
131
+ @new_post.stub!(:allow_comments).and_return('no')
132
+
133
+ concat(semantic_form_for(@new_post) do |builder|
134
+ concat(builder.input(:allow_comments, :as => :boolean, :checked_value => 'yes', :unchecked_value => 'no'))
135
+ end)
136
+
137
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"][@value="yes"]:not([@checked])')
138
+ end
139
+
140
+ it 'should generate a label and a checkbox even if no object is given' do
141
+ concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
142
+ concat(builder.input(:allow_comments, :as => :boolean))
143
+ end)
144
+
145
+ output_buffer.should have_tag('form div.clearfix div.input ul li label[@for="project_allow_comments"]')
146
+ output_buffer.should have_tag('form div.clearfix div.input ul li label', /Allow comments/)
147
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"]')
148
+
149
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input#project_allow_comments')
150
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@type="checkbox"]')
151
+ output_buffer.should have_tag('form div.clearfix div.input ul li label input[@name="project[allow_comments]"]')
152
+ end
153
+
154
+ context "when required" do
155
+
156
+ it "should add the required attribute to the input's html options" do
157
+ with_config :use_required_attribute, true do
158
+ concat(semantic_form_for(@new_post) do |builder|
159
+ concat(builder.input(:title, :as => :boolean, :required => true))
160
+ end)
161
+ output_buffer.should have_tag("input[@required]")
162
+ end
163
+ end
164
+
165
+ it "should not add the required attribute to the boolean fields input's html options" do
166
+ with_config :use_required_attribute, true do
167
+ concat(semantic_form_for(@new_post) do |builder|
168
+ concat(builder.input(:title, :as => :boolean))
169
+ end)
170
+ output_buffer.should_not have_tag("input[@required]")
171
+ end
172
+ end
173
+
174
+ end
175
+
176
+ describe "when namespace is provided" do
177
+
178
+ before do
179
+ @output_buffer = ''
180
+ mock_everything
181
+ Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
182
+
183
+ concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
184
+ concat(builder.input(:allow_comments, :as => :boolean))
185
+ end)
186
+ end
187
+
188
+ it_should_have_input_wrapper_with_id("context2_post_allow_comments_input")
189
+ it_should_have_an_inline_label_for("context2_post_allow_comments")
190
+
191
+ end
192
+
193
+ end
@@ -0,0 +1,439 @@
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")
20
+ it_should_have_input_wrapper_with_class(:clearfix)
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.input')
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.clearfix label')
33
+ output_buffer.should have_tag('form div.clearfix 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.clearfix > 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.clearfix div.input ul')
42
+ output_buffer.should have_tag('form div.clearfix div.input 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 li 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 ul li 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.clearfix > input[@type='hidden']", :count => 1)
73
+ end
74
+
75
+ describe "each choice" do
76
+
77
+ it 'should not give the choice label the .label class' do
78
+ output_buffer.should_not have_tag('li.choice label.label')
79
+ end
80
+
81
+ it 'should not be marked as required' do
82
+ output_buffer.should_not have_tag('li.choice 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.clearfix div.input ul li label', /#{post.to_label}/)
88
+ output_buffer.should have_tag("form div.clearfix div.input ul li label[@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.clearfix div.input ul li.post_#{post.id} label")
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.clearfix div.input ul li label input#author_post_ids_#{post.id}")
101
+ output_buffer.should have_tag("form div.clearfix div.input ul li label 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.clearfix > 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.input and the ul' do
110
+ output_buffer.should have_tag("form div.clearfix > input[@type=hidden][@name='author[post_ids][]'][@value=''] + div.input ul", :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.clearfix > 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.clearfix div.input ul li label input#author_post_ids_#{post.id}")
126
+ output_buffer.should have_tag("form div.clearfix div.input ul li label 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.clearfix div.input ul li label 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.clearfix > 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.clearfix div.input ul li 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.clearfix div.input ul li label', /#{author.to_label}/)
156
+ output_buffer.should have_tag("form div.clearfix div.input ul li label[@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.clearfix div.input ul li label input#project_author_id_#{author.id}")
163
+ output_buffer.should have_tag("form div.clearfix div.input ul li label input[@type='checkbox']")
164
+ output_buffer.should have_tag("form div.clearfix div.input ul li label input[@value='#{author.id}']")
165
+ output_buffer.should have_tag("form div.clearfix div.input ul li label 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.clearfix div.input ul li label') 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.clearfix div.input ul li label input#author_post_ids_#{post.id}")
194
+ output_buffer.should have_tag("form div.clearfix div.input ul li label 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.clearfix div.input ul li label input[@checked='checked']")
201
+ end
202
+
203
+ it 'should not generate empty hidden inputs' do
204
+ output_buffer.should_not have_tag("form div.clearfix div.input ul li label 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.clearfix div.input ul li label 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.clearfix div.input ul li label input[@disabled='disabled']", :count => 1)
238
+ output_buffer.should have_tag("form div.clearfix div.input ul li label[@for='post_author_ids_#{@fred.id}']", /fred/i)
239
+ output_buffer.should have_tag("form div.clearfix div.input ul li label 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.clearfix div.input ul li label input[@disabled='disabled']", :count => 2)
254
+ output_buffer.should have_tag("form div.clearfix div.input ul li label[@for='post_author_ids_#{@bob.id}']", /bob/i)
255
+ output_buffer.should have_tag("form div.clearfix div.input ul li label input[@disabled='disabled'][@value='#{@bob.id}']")
256
+ output_buffer.should have_tag("form div.clearfix div.input ul li label[@for='post_author_ids_#{@fred.id}']", /fred/i)
257
+ output_buffer.should have_tag("form div.clearfix div.input ul li label 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.clearfix > 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.clearfix > 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.clearfix > 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.clearfix > 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(3).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.clearfix div.input ul li label input[@value='fiction'][@checked='checked']")
391
+ output_buffer.should have_tag("form div.clearfix div.input ul li label 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 li label[@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 collection is an array" do
415
+ before do
416
+ @output_buffer = ''
417
+ @_collection = [["First", 1], ["Second", 2]]
418
+ mock_everything
419
+ Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
420
+
421
+ concat(semantic_form_for(@fred) do |builder|
422
+ concat(builder.input(:posts, :as => :check_boxes, :collection => @_collection))
423
+ end)
424
+ end
425
+
426
+ it "should use array items for labels and values" do
427
+ @_collection.each do |post|
428
+ output_buffer.should have_tag('form div.clearfix div.input ul li label', /#{post.first}/)
429
+ output_buffer.should have_tag("form div.clearfix div.input ul li label[@for='author_post_ids_#{post.last}']")
430
+ end
431
+ end
432
+
433
+ it "should not check any items" do
434
+ output_buffer.should have_tag('form li input[@checked]', :count => 0)
435
+ end
436
+ end
437
+
438
+ end
439
+