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