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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +123 -0
- data/LICENSE.txt +20 -0
- data/README.md +159 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/formtastic-bootstrap.gemspec +128 -0
- data/lib/action_view/helpers/text_field_date_helper.rb +166 -0
- data/lib/formtastic-bootstrap.rb +5 -0
- data/lib/formtastic-bootstrap/form_builder.rb +38 -0
- data/lib/formtastic-bootstrap/helpers.rb +19 -0
- data/lib/formtastic-bootstrap/helpers/buttons_helper.rb +47 -0
- data/lib/formtastic-bootstrap/helpers/fieldset_wrapper.rb +37 -0
- data/lib/formtastic-bootstrap/helpers/input_helper.rb +12 -0
- data/lib/formtastic-bootstrap/helpers/inputs_helper.rb +36 -0
- data/lib/formtastic-bootstrap/inputs.rb +28 -0
- data/lib/formtastic-bootstrap/inputs/base.rb +22 -0
- data/lib/formtastic-bootstrap/inputs/base/choices.rb +49 -0
- data/lib/formtastic-bootstrap/inputs/base/errors.rb +48 -0
- data/lib/formtastic-bootstrap/inputs/base/hints.rb +27 -0
- data/lib/formtastic-bootstrap/inputs/base/html.rb +21 -0
- data/lib/formtastic-bootstrap/inputs/base/labelling.rb +18 -0
- data/lib/formtastic-bootstrap/inputs/base/stringish.rb +18 -0
- data/lib/formtastic-bootstrap/inputs/base/timeish.rb +35 -0
- data/lib/formtastic-bootstrap/inputs/base/wrapping.rb +56 -0
- data/lib/formtastic-bootstrap/inputs/boolean_input.rb +33 -0
- data/lib/formtastic-bootstrap/inputs/check_boxes_input.rb +35 -0
- data/lib/formtastic-bootstrap/inputs/date_input.rb +16 -0
- data/lib/formtastic-bootstrap/inputs/datetime_input.rb +19 -0
- data/lib/formtastic-bootstrap/inputs/email_input.rb +15 -0
- data/lib/formtastic-bootstrap/inputs/file_input.rb +14 -0
- data/lib/formtastic-bootstrap/inputs/hidden_input.rb +12 -0
- data/lib/formtastic-bootstrap/inputs/number_input.rb +15 -0
- data/lib/formtastic-bootstrap/inputs/password_input.rb +15 -0
- data/lib/formtastic-bootstrap/inputs/phone_input.rb +15 -0
- data/lib/formtastic-bootstrap/inputs/radio_input.rb +32 -0
- data/lib/formtastic-bootstrap/inputs/range_input.rb +15 -0
- data/lib/formtastic-bootstrap/inputs/search_input.rb +15 -0
- data/lib/formtastic-bootstrap/inputs/select_input.rb +14 -0
- data/lib/formtastic-bootstrap/inputs/string_input.rb +15 -0
- data/lib/formtastic-bootstrap/inputs/text_input.rb +14 -0
- data/lib/formtastic-bootstrap/inputs/time_input.rb +16 -0
- data/lib/formtastic-bootstrap/inputs/url_input.rb +14 -0
- data/spec/builder/errors_spec.rb +214 -0
- data/spec/builder/semantic_fields_for_spec.rb +130 -0
- data/spec/helpers/input_helper_spec.rb +956 -0
- data/spec/helpers/inputs_helper_spec.rb +577 -0
- data/spec/inputs/boolean_input_spec.rb +193 -0
- data/spec/inputs/check_boxes_input_spec.rb +439 -0
- data/spec/inputs/date_input_spec.rb +147 -0
- data/spec/inputs/datetime_input_spec.rb +101 -0
- data/spec/inputs/email_input_spec.rb +59 -0
- data/spec/inputs/file_input_spec.rb +63 -0
- data/spec/inputs/hidden_input_spec.rb +122 -0
- data/spec/inputs/number_input_spec.rb +787 -0
- data/spec/inputs/password_input_spec.rb +73 -0
- data/spec/inputs/phone_input_spec.rb +59 -0
- data/spec/inputs/radio_input_spec.rb +240 -0
- data/spec/inputs/range_input_spec.rb +479 -0
- data/spec/inputs/search_input_spec.rb +59 -0
- data/spec/inputs/select_input_spec.rb +567 -0
- data/spec/inputs/string_input_spec.rb +182 -0
- data/spec/inputs/text_input_spec.rb +163 -0
- data/spec/inputs/time_input_spec.rb +206 -0
- data/spec/inputs/url_input_spec.rb +59 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/custom_macros.rb +704 -0
- data/spec/support/depracation.rb +6 -0
- data/spec/support/formtastic_spec_helper.rb +382 -0
- metadata +204 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'search input' do
|
5
|
+
|
6
|
+
include FormtasticSpecHelper
|
7
|
+
|
8
|
+
before do
|
9
|
+
@output_buffer = ''
|
10
|
+
mock_everything
|
11
|
+
Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "when object is provided" do
|
15
|
+
before do
|
16
|
+
concat(semantic_form_for(@new_post) do |builder|
|
17
|
+
concat(builder.input(:search))
|
18
|
+
end)
|
19
|
+
end
|
20
|
+
|
21
|
+
it_should_have_input_wrapper_with_class(:search)
|
22
|
+
it_should_have_input_wrapper_with_class(:clearfix)
|
23
|
+
it_should_have_input_wrapper_with_class(:stringish)
|
24
|
+
it_should_have_input_class_in_the_right_place
|
25
|
+
it_should_have_input_wrapper_with_id("post_search_input")
|
26
|
+
it_should_have_label_with_text(/Search/)
|
27
|
+
it_should_have_label_for("post_search")
|
28
|
+
it_should_have_input_with_id("post_search")
|
29
|
+
it_should_have_input_with_type(:search)
|
30
|
+
it_should_have_input_with_name("post[search]")
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "when namespace is provided" do
|
35
|
+
|
36
|
+
before do
|
37
|
+
concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
|
38
|
+
concat(builder.input(:search))
|
39
|
+
end)
|
40
|
+
end
|
41
|
+
|
42
|
+
it_should_have_input_wrapper_with_id("context2_post_search_input")
|
43
|
+
it_should_have_label_and_input_with_id("context2_post_search")
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "when required" do
|
48
|
+
it "should add the required attribute to the input's html options" do
|
49
|
+
with_config :use_required_attribute, true do
|
50
|
+
concat(semantic_form_for(@new_post) do |builder|
|
51
|
+
concat(builder.input(:title, :as => :search, :required => true))
|
52
|
+
end)
|
53
|
+
output_buffer.should have_tag("input[@required]")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,567 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'select input' do
|
5
|
+
|
6
|
+
include FormtasticSpecHelper
|
7
|
+
|
8
|
+
before do
|
9
|
+
@output_buffer = ''
|
10
|
+
mock_everything
|
11
|
+
Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'explicit values' do
|
15
|
+
describe 'using an array of values' do
|
16
|
+
before do
|
17
|
+
@array_with_values = ["Title A", "Title B", "Title C"]
|
18
|
+
@array_with_keys_and_values = [["Title D", 1], ["Title E", 2], ["Title F", 3]]
|
19
|
+
concat(semantic_form_for(@new_post) do |builder|
|
20
|
+
concat(builder.input(:title, :as => :select, :collection => @array_with_values))
|
21
|
+
concat(builder.input(:title, :as => :select, :collection => @array_with_keys_and_values))
|
22
|
+
end)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should have a option for each key and/or value' do
|
26
|
+
@array_with_values.each do |v|
|
27
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{v}']", /^#{v}$/)
|
28
|
+
end
|
29
|
+
@array_with_keys_and_values.each do |v|
|
30
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{v.second}']", /^#{v.first}$/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "using a related model without reflection's options (Mongoid Document)" do
|
36
|
+
before do
|
37
|
+
@new_post.stub!(:mongoid_reviewer)
|
38
|
+
concat(semantic_form_for(@new_post) do |builder|
|
39
|
+
concat(builder.input(:mongoid_reviewer, :as => :select))
|
40
|
+
end)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should draw select options' do
|
44
|
+
output_buffer.should have_tag('form div.clearfix div.input select')
|
45
|
+
output_buffer.should have_tag('form div.clearfix div.input select#post_reviewer_id')
|
46
|
+
output_buffer.should_not have_tag('form div.clearfix div.input select#post_mongoid_reviewer_id')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'using a range' do
|
51
|
+
before do
|
52
|
+
@range_with_values = 1..5
|
53
|
+
concat(semantic_form_for(@new_post) do |builder|
|
54
|
+
concat(builder.input(:title, :as => :select, :collection => @range_with_values))
|
55
|
+
end)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should have an option for each value' do
|
59
|
+
@range_with_values.each do |v|
|
60
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{v}']", /^#{v}$/)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'using a string' do
|
66
|
+
before do
|
67
|
+
@string ="<option value='0'>0</option><option value='1'>1</option>"
|
68
|
+
concat(semantic_form_for(@new_post) do |builder|
|
69
|
+
concat(builder.input(:title, :as => :select, :collection => @string))
|
70
|
+
end)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should render select options using provided HTML string' do
|
74
|
+
2.times do |v|
|
75
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{v}']", /^#{v}$/)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'for boolean columns' do
|
82
|
+
# describe 'default formtastic locale' do
|
83
|
+
# before do
|
84
|
+
# # Note: Works, but something like Formtastic.root.join(...) would probably be "safer".
|
85
|
+
# ::I18n.load_path = [File.join(File.dirname(__FILE__), *%w[.. .. lib locale en.yml])]
|
86
|
+
# ::I18n.backend.send(:init_translations)
|
87
|
+
#
|
88
|
+
# concat(semantic_form_for(@new_post) do |builder|
|
89
|
+
# concat(builder.input(:published, :as => :select))
|
90
|
+
# end)
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# after do
|
94
|
+
# ::I18n.backend.store_translations :en, {}
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# it 'should render a select with at least options: true/false' do
|
98
|
+
# output_buffer.should have_tag("form div.clearfix div.input select option[@value='true']", /^Yes$/)
|
99
|
+
# output_buffer.should have_tag("form div.clearfix div.input select option[@value='false']", /^No$/)
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
|
103
|
+
describe 'custom locale' do
|
104
|
+
before do
|
105
|
+
@boolean_select_labels = {:yes => 'Yep', :no => 'Nope'}
|
106
|
+
::I18n.backend.store_translations :en, :formtastic => @boolean_select_labels
|
107
|
+
|
108
|
+
concat(semantic_form_for(@new_post) do |builder|
|
109
|
+
concat(builder.input(:published, :as => :select))
|
110
|
+
end)
|
111
|
+
end
|
112
|
+
|
113
|
+
after do
|
114
|
+
::I18n.backend.store_translations :en, {}
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should render a select with at least options: true/false' do
|
118
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='true']", /#{@boolean_select_labels[:yes]}/)
|
119
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='false']", /#{@boolean_select_labels[:no]}/)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'for a belongs_to association' do
|
125
|
+
before do
|
126
|
+
concat(semantic_form_for(@new_post) do |builder|
|
127
|
+
concat(builder.input(:author, :as => :select))
|
128
|
+
concat(builder.input(:reviewer, :as => :select))
|
129
|
+
end)
|
130
|
+
end
|
131
|
+
|
132
|
+
it_should_have_input_wrapper_with_class("select")
|
133
|
+
it_should_have_input_wrapper_with_class(:clearfix)
|
134
|
+
it_should_have_input_class_in_the_right_place
|
135
|
+
it_should_have_input_wrapper_with_id("post_author_input")
|
136
|
+
it_should_have_label_with_text(/Author/)
|
137
|
+
it_should_have_label_for('post_author_id')
|
138
|
+
it_should_apply_error_logic_for_input_type(:select)
|
139
|
+
it_should_call_find_on_association_class_when_no_collection_is_provided(:select)
|
140
|
+
it_should_use_the_collection_when_provided(:select, 'option')
|
141
|
+
|
142
|
+
it 'should have a select inside the wrapper' do
|
143
|
+
output_buffer.should have_tag('form div.clearfix div.input select')
|
144
|
+
output_buffer.should have_tag('form div.clearfix div.input select#post_author_id')
|
145
|
+
output_buffer.should have_tag('form div.clearfix div.input select#post_reviewer_id')
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should have a valid name' do
|
149
|
+
output_buffer.should have_tag("form div.clearfix div.input select[@name='post[author_id]']")
|
150
|
+
output_buffer.should_not have_tag("form div.clearfix div.input select[@name='post[author_id][]']")
|
151
|
+
output_buffer.should_not have_tag("form div.clearfix div.input select[@name='post[reviewer_id][]']")
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should not create a multi-select' do
|
155
|
+
output_buffer.should_not have_tag('form div.clearfix div.input select[@multiple]')
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should create a select without size' do
|
159
|
+
output_buffer.should_not have_tag('form div.clearfix div.input select[@size]')
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should have a blank option' do
|
163
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='']")
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should have a select option for each Author' do
|
167
|
+
output_buffer.should have_tag("form div.clearfix div.input select[@name='post[author_id]'] option", :count => ::Author.all.size + 1)
|
168
|
+
::Author.all.each do |author|
|
169
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{author.id}']", /#{author.to_label}/)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should have one option with a "selected" attribute (bob)' do
|
174
|
+
output_buffer.should have_tag("form div.clearfix div.input select[@name='post[author_id]'] option[@selected]", :count => 1)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should not singularize the association name' do
|
178
|
+
@new_post.stub!(:author_status).and_return(@bob)
|
179
|
+
@new_post.stub!(:author_status_id).and_return(@bob.id)
|
180
|
+
@new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :integer, :limit => 255))
|
181
|
+
|
182
|
+
concat(semantic_form_for(@new_post) do |builder|
|
183
|
+
concat(builder.input(:author_status, :as => :select))
|
184
|
+
end)
|
185
|
+
|
186
|
+
output_buffer.should have_tag('form div.clearfix div.input select#post_author_status_id')
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "for a belongs_to association with :group_by => :author" do
|
191
|
+
it "should call author.posts" do
|
192
|
+
::Author.stub!(:reflect_on_all_associations).and_return { |macro| macro == :has_many ? [mock('reflection', :klass => Post, :name => :posts)] : []}
|
193
|
+
|
194
|
+
[@freds_post].each { |post| post.stub!(:to_label).and_return("Post - #{post.id}") }
|
195
|
+
@fred.should_receive(:posts)
|
196
|
+
|
197
|
+
concat(semantic_form_for(@new_post) do |builder|
|
198
|
+
concat(builder.input(:main_post, :as => :select, :group_by => :author ) )
|
199
|
+
end)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "for a belongs_to association with :conditions" do
|
204
|
+
before do
|
205
|
+
::Post.stub!(:reflect_on_association).with(:author).and_return do
|
206
|
+
mock = mock('reflection', :options => {:conditions => {:active => true}}, :klass => ::Author, :macro => :belongs_to)
|
207
|
+
mock.stub!(:[]).with(:class_name).and_return("Author")
|
208
|
+
mock
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should call author.find with association conditions" do
|
213
|
+
::Author.should_receive(:scoped).with(:conditions => {:active => true})
|
214
|
+
|
215
|
+
semantic_form_for(@new_post) do |builder|
|
216
|
+
concat(builder.input(:author, :as => :select))
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should call author.find with association conditions and find_options conditions" do
|
221
|
+
::Author.should_receive(:scoped).with(:conditions => {:active => true})
|
222
|
+
::Author.should_receive(:where).with({:publisher => true})
|
223
|
+
|
224
|
+
semantic_form_for(@new_post) do |builder|
|
225
|
+
concat(builder.input(:author, :as => :select, :find_options => {:conditions => {:publisher => true}}))
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe 'for a belongs_to association with :group_by => :continent' do
|
231
|
+
before do
|
232
|
+
@authors = [@bob, @fred, @fred, @fred]
|
233
|
+
::Author.stub!(:find).and_return(@authors)
|
234
|
+
@continent_names = %w(Europe Africa)
|
235
|
+
@continents = (0..1).map { |i| c = ::Continent.new; c.stub!(:id).and_return(100 - i);c }
|
236
|
+
@authors[0..1].each_with_index { |author, i| author.stub!(:continent).and_return(@continents[i]) }
|
237
|
+
|
238
|
+
::Continent.stub!(:reflect_on_all_associations).and_return { |macro| macro == :has_many ? [mock('reflection', :klass => Author, :name => :authors)] : [] }
|
239
|
+
::Continent.stub!(:reflect_on_association).and_return {|column_name| mock('reflection', :klass => Author) if column_name == :authors}
|
240
|
+
::Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Continent, :macro => :belongs_to) if column_name == :continent }
|
241
|
+
|
242
|
+
|
243
|
+
@continents.each_with_index do |continent, i|
|
244
|
+
continent.stub!(:to_label).and_return(@continent_names[i])
|
245
|
+
continent.stub!(:authors).and_return([@authors[i]])
|
246
|
+
end
|
247
|
+
|
248
|
+
concat(semantic_form_for(@new_post) do |builder|
|
249
|
+
concat(builder.input(:author, :as => :select, :group_by => :continent ) )
|
250
|
+
concat(builder.input(:author, :as => :select, :group_by => :continent, :group_label => :id ) )
|
251
|
+
concat(builder.input(:author, :as => :select, :group_by => :continent, :member_label => :login ) )
|
252
|
+
concat(builder.input(:author, :as => :select, :group_by => :continent, :member_label => :login, :group_label => :id ) )
|
253
|
+
end)
|
254
|
+
end
|
255
|
+
|
256
|
+
it_should_have_input_wrapper_with_class("select")
|
257
|
+
it_should_have_input_wrapper_with_id("post_author_input")
|
258
|
+
it_should_have_label_with_text(/Author/)
|
259
|
+
it_should_have_label_for('post_author_id')
|
260
|
+
|
261
|
+
# TODO, need to find a way to repeat some of the specs and logic from the belongs_to specs without grouping
|
262
|
+
|
263
|
+
0.upto(1) do |i|
|
264
|
+
it 'should have all option groups and the right values' do
|
265
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='#{@continent_names[i]}']", @authors[i].to_label)
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'should have custom group labels' do
|
269
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='#{@continents[i].id}']", @authors[i].to_label)
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'should have custom author labels' do
|
273
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='#{@continent_names[i]}']", @authors[i].login)
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'should have custom author and group labels' do
|
277
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='#{@continents[i].id}']", @authors[i].login)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'should have no duplicate groups' do
|
282
|
+
output_buffer.should have_tag('form div.clearfix div.input select optgroup', :count => 8)
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'should sort the groups on the label method' do
|
286
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='Africa']")
|
287
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='99']")
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'should call find with :include for more optimized queries' do
|
291
|
+
Author.should_receive(:where).with(:include => :continent)
|
292
|
+
|
293
|
+
semantic_form_for(@new_post) do |builder|
|
294
|
+
concat(builder.input(:author, :as => :select, :group_by => :continent ) )
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
describe 'for a has_many association' do
|
300
|
+
before do
|
301
|
+
concat(semantic_form_for(@fred) do |builder|
|
302
|
+
concat(builder.input(:posts, :as => :select))
|
303
|
+
end)
|
304
|
+
end
|
305
|
+
|
306
|
+
it_should_have_input_wrapper_with_class("select")
|
307
|
+
it_should_have_input_wrapper_with_id("author_posts_input")
|
308
|
+
it_should_have_label_with_text(/Post/)
|
309
|
+
it_should_have_label_for('author_post_ids')
|
310
|
+
it_should_apply_error_logic_for_input_type(:select)
|
311
|
+
it_should_call_find_on_association_class_when_no_collection_is_provided(:select)
|
312
|
+
it_should_use_the_collection_when_provided(:select, 'option')
|
313
|
+
|
314
|
+
it 'should have a select inside the wrapper' do
|
315
|
+
output_buffer.should have_tag('form div.clearfix div.input select')
|
316
|
+
output_buffer.should have_tag('form div.clearfix div.input select#author_post_ids')
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'should have a multi-select select' do
|
320
|
+
output_buffer.should have_tag('form div.clearfix div.input select[@multiple="multiple"]')
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'should append [] to the name attribute for multiple select' do
|
324
|
+
output_buffer.should have_tag('form div.clearfix div.input select[@multiple="multiple"][@name="author[post_ids][]"]')
|
325
|
+
end
|
326
|
+
|
327
|
+
it 'should have a select option for each Post' do
|
328
|
+
output_buffer.should have_tag('form div.clearfix div.input select option', :count => ::Post.all.size)
|
329
|
+
::Post.all.each do |post|
|
330
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{post.id}']", /#{post.to_label}/)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'should not have a blank option by default' do
|
335
|
+
output_buffer.should_not have_tag("form div.clearfix div.input select option[@value='']")
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'should respect the :include_blank option for single selects' do
|
339
|
+
concat(semantic_form_for(@fred) do |builder|
|
340
|
+
concat(builder.input(:posts, :as => :select, :multiple => false, :include_blank => true))
|
341
|
+
end)
|
342
|
+
|
343
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='']")
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'should respect the :include_blank option for multiple selects' do
|
347
|
+
concat(semantic_form_for(@fred) do |builder|
|
348
|
+
concat(builder.input(:posts, :as => :select, :multiple => true, :include_blank => true))
|
349
|
+
end)
|
350
|
+
|
351
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='']")
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'should have one option with a "selected" attribute' do
|
355
|
+
output_buffer.should have_tag('form div.clearfix div.input select option[@selected]', :count => 1)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
describe 'for a has_and_belongs_to_many association' do
|
360
|
+
before do
|
361
|
+
concat(semantic_form_for(@freds_post) do |builder|
|
362
|
+
concat(builder.input(:authors, :as => :select))
|
363
|
+
end)
|
364
|
+
end
|
365
|
+
|
366
|
+
it_should_have_input_wrapper_with_class("select")
|
367
|
+
it_should_have_input_wrapper_with_id("post_authors_input")
|
368
|
+
it_should_have_label_with_text(/Author/)
|
369
|
+
it_should_have_label_for('post_author_ids')
|
370
|
+
it_should_apply_error_logic_for_input_type(:select)
|
371
|
+
it_should_call_find_on_association_class_when_no_collection_is_provided(:select)
|
372
|
+
it_should_use_the_collection_when_provided(:select, 'option')
|
373
|
+
|
374
|
+
it 'should have a select inside the wrapper' do
|
375
|
+
output_buffer.should have_tag('form div.clearfix div.input select')
|
376
|
+
output_buffer.should have_tag('form div.clearfix div.input select#post_author_ids')
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'should have a multi-select select' do
|
380
|
+
output_buffer.should have_tag('form div.clearfix div.input select[@multiple="multiple"]')
|
381
|
+
end
|
382
|
+
|
383
|
+
it 'should have a select option for each Author' do
|
384
|
+
output_buffer.should have_tag('form div.clearfix div.input select option', :count => ::Author.all.size)
|
385
|
+
::Author.all.each do |author|
|
386
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{author.id}']", /#{author.to_label}/)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
it 'should not have a blank option by default' do
|
391
|
+
output_buffer.should_not have_tag("form div.clearfix div.input select option[@value='']")
|
392
|
+
end
|
393
|
+
|
394
|
+
it 'should respect the :include_blank option for single selects' do
|
395
|
+
concat(semantic_form_for(@freds_post) do |builder|
|
396
|
+
concat(builder.input(:authors, :as => :select, :multiple => false, :include_blank => true))
|
397
|
+
end)
|
398
|
+
|
399
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='']")
|
400
|
+
end
|
401
|
+
|
402
|
+
it 'should respect the :include_blank option for multiple selects' do
|
403
|
+
concat(semantic_form_for(@freds_post) do |builder|
|
404
|
+
concat(builder.input(:authors, :as => :select, :multiple => true, :include_blank => true))
|
405
|
+
end)
|
406
|
+
|
407
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='']")
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'should have one option with a "selected" attribute' do
|
411
|
+
output_buffer.should have_tag('form div.clearfix div.input select option[@selected]', :count => 1)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe 'when :prompt => "choose something" is set' do
|
416
|
+
before do
|
417
|
+
@new_post.stub!(:author_id).and_return(nil)
|
418
|
+
concat(semantic_form_for(@new_post) do |builder|
|
419
|
+
concat(builder.input(:author, :as => :select, :prompt => "choose author"))
|
420
|
+
end)
|
421
|
+
end
|
422
|
+
|
423
|
+
it 'should have a select with prompt' do
|
424
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='']", /choose author/, :count => 1)
|
425
|
+
end
|
426
|
+
|
427
|
+
it 'should not have a blank select option' do
|
428
|
+
output_buffer.should_not have_tag("form div.clearfix div.input select option[@value='']", "")
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
describe 'when no object is given' do
|
433
|
+
before(:each) do
|
434
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
435
|
+
concat(builder.input(:author, :as => :select, :collection => ::Author.all))
|
436
|
+
end)
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'should generate label' do
|
440
|
+
output_buffer.should have_tag('form div.clearfix label', /Author/)
|
441
|
+
output_buffer.should have_tag("form div.clearfix label[@for='project_author']")
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'should generate select inputs' do
|
445
|
+
output_buffer.should have_tag('form div.clearfix div.input select#project_author')
|
446
|
+
output_buffer.should have_tag('form div.clearfix div.input select option', :count => ::Author.all.size + 1)
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'should generate an option to each item' do
|
450
|
+
::Author.all.each do |author|
|
451
|
+
output_buffer.should have_tag("form div.clearfix div.input select option[@value='#{author.id}']", /#{author.to_label}/)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
describe 'when no association exists' do
|
457
|
+
|
458
|
+
it 'should still generate a valid name attribute' do
|
459
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
460
|
+
concat(builder.input(:author_name, :as => :select, :collection => ::Author.all))
|
461
|
+
end)
|
462
|
+
output_buffer.should have_tag("form div.clearfix div.input select[@name='project[author_name]']")
|
463
|
+
end
|
464
|
+
|
465
|
+
describe 'and :multiple is set to true through :input_html' do
|
466
|
+
it "should make the select a multi-select" do
|
467
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
468
|
+
concat(builder.input(:author_name, :as => :select, :input_html => {:multiple => true} ))
|
469
|
+
end)
|
470
|
+
output_buffer.should have_tag("form div.clearfix div.input select[@multiple]")
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
describe 'and :multiple is set to true' do
|
475
|
+
it "should make the select a multi-select" do
|
476
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
477
|
+
concat(builder.input(:author_name, :as => :select, :multiple => true, :collection => ["Fred", "Bob"]))
|
478
|
+
end)
|
479
|
+
output_buffer.should have_tag("form div.clearfix div.input select[@multiple]")
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
|
485
|
+
describe 'when a grouped collection collection is given' do
|
486
|
+
before(:each) do
|
487
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
488
|
+
@grouped_opts = [['one', ['pencil', 'crayon', 'pen']],
|
489
|
+
['two', ['eyes', 'hands', 'feet']],
|
490
|
+
['three', ['wickets', 'witches', 'blind mice']]]
|
491
|
+
concat(builder.input(:author, :as => :select, :collection => grouped_options_for_select(@grouped_opts, "hands")))
|
492
|
+
end)
|
493
|
+
end
|
494
|
+
|
495
|
+
it 'should generate an option to each item' do
|
496
|
+
@grouped_opts.each do |opt_pair|
|
497
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='#{opt_pair[0]}']")
|
498
|
+
opt_pair[1].each do |v|
|
499
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup[@label='#{opt_pair[0]}'] option[@value='#{v}']")
|
500
|
+
end
|
501
|
+
end
|
502
|
+
output_buffer.should have_tag("form div.clearfix div.input select optgroup option[@selected]","hands")
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
describe "enum" do
|
507
|
+
before do
|
508
|
+
@output_buffer = ''
|
509
|
+
@some_meta_descriptions = ["One", "Two", "Three"]
|
510
|
+
@new_post.stub!(:meta_description).any_number_of_times
|
511
|
+
end
|
512
|
+
|
513
|
+
describe ":as is not set" do
|
514
|
+
before do
|
515
|
+
concat(semantic_form_for(@new_post) do |builder|
|
516
|
+
concat(builder.input(:meta_description, :collection => @some_meta_descriptions))
|
517
|
+
end)
|
518
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
519
|
+
concat(builder.input(:meta_description, :collection => @some_meta_descriptions))
|
520
|
+
end)
|
521
|
+
end
|
522
|
+
|
523
|
+
it "should render a select field" do
|
524
|
+
output_buffer.should have_tag("form div.clearfix div.input select", :count => 2)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
describe ":as is set" do
|
529
|
+
before do
|
530
|
+
# Should not be a case, but just checking :as got highest priority in setting input type.
|
531
|
+
concat(semantic_form_for(@new_post) do |builder|
|
532
|
+
concat(builder.input(:meta_description, :as => :string, :collection => @some_meta_descriptions))
|
533
|
+
end)
|
534
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
535
|
+
concat(builder.input(:meta_description, :as => :string, :collection => @some_meta_descriptions))
|
536
|
+
end)
|
537
|
+
end
|
538
|
+
|
539
|
+
it "should render a text field" do
|
540
|
+
output_buffer.should have_tag("form div.clearfix div.input input[@type='text']", :count => 2)
|
541
|
+
end
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
describe 'when a namespace is provided' do
|
546
|
+
before do
|
547
|
+
concat(semantic_form_for(@freds_post, :namespace => 'context2') do |builder|
|
548
|
+
concat(builder.input(:authors, :as => :select))
|
549
|
+
end)
|
550
|
+
end
|
551
|
+
it_should_have_input_wrapper_with_id("context2_post_authors_input")
|
552
|
+
it_should_have_select_with_id("context2_post_author_ids")
|
553
|
+
it_should_have_label_for("context2_post_author_ids")
|
554
|
+
end
|
555
|
+
|
556
|
+
context "when required" do
|
557
|
+
it "should add the required attribute to the select's html options" do
|
558
|
+
with_config :use_required_attribute, true do
|
559
|
+
concat(semantic_form_for(@new_post) do |builder|
|
560
|
+
concat(builder.input(:author, :as => :select, :required => true))
|
561
|
+
end)
|
562
|
+
output_buffer.should have_tag("select[@required]")
|
563
|
+
end
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
end
|