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,73 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'password 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(:title, :as => :password))
|
15
|
+
end)
|
16
|
+
end
|
17
|
+
|
18
|
+
it_should_have_input_wrapper_with_class(:password)
|
19
|
+
it_should_have_input_wrapper_with_class(:clearfix)
|
20
|
+
it_should_have_input_wrapper_with_class(:stringish)
|
21
|
+
it_should_have_input_class_in_the_right_place
|
22
|
+
it_should_have_input_wrapper_with_id("post_title_input")
|
23
|
+
it_should_have_label_with_text(/Title/)
|
24
|
+
it_should_have_label_for("post_title")
|
25
|
+
it_should_have_input_with_id("post_title")
|
26
|
+
it_should_have_input_with_type(:password)
|
27
|
+
it_should_have_input_with_name("post[title]")
|
28
|
+
it_should_have_maxlength_matching_column_limit
|
29
|
+
it_should_use_default_text_field_size_when_not_nil(:string)
|
30
|
+
it_should_not_use_default_text_field_size_when_nil(:string)
|
31
|
+
it_should_apply_custom_input_attributes_when_input_html_provided(:string)
|
32
|
+
it_should_apply_custom_for_to_label_when_input_html_id_provided(:string)
|
33
|
+
it_should_apply_error_logic_for_input_type(:password)
|
34
|
+
|
35
|
+
describe "when no object is provided" do
|
36
|
+
before do
|
37
|
+
concat(semantic_form_for(:project, :url => 'http://test.host/') do |builder|
|
38
|
+
concat(builder.input(:title, :as => :password))
|
39
|
+
end)
|
40
|
+
end
|
41
|
+
|
42
|
+
it_should_have_label_with_text(/Title/)
|
43
|
+
it_should_have_label_for("project_title")
|
44
|
+
it_should_have_input_with_id("project_title")
|
45
|
+
it_should_have_input_with_type(:password)
|
46
|
+
it_should_have_input_with_name("project[title]")
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "when namespace is provided" do
|
50
|
+
|
51
|
+
before do
|
52
|
+
concat(semantic_form_for(@new_post, :namespace => "context2") do |builder|
|
53
|
+
concat(builder.input(:title, :as => :password))
|
54
|
+
end)
|
55
|
+
end
|
56
|
+
|
57
|
+
it_should_have_input_wrapper_with_id("context2_post_title_input")
|
58
|
+
it_should_have_label_and_input_with_id("context2_post_title")
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "when required" do
|
63
|
+
it "should add the required attribute to the input's html options" do
|
64
|
+
with_config :use_required_attribute, true do
|
65
|
+
concat(semantic_form_for(@new_post) do |builder|
|
66
|
+
concat(builder.input(:title, :as => :password, :required => true))
|
67
|
+
end)
|
68
|
+
output_buffer.should have_tag("input[@required]")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'phone 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(:phone))
|
18
|
+
end)
|
19
|
+
end
|
20
|
+
|
21
|
+
it_should_have_input_wrapper_with_class(:phone)
|
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_phone_input")
|
26
|
+
it_should_have_label_with_text(/Phone/)
|
27
|
+
it_should_have_label_for("post_phone")
|
28
|
+
it_should_have_input_with_id("post_phone")
|
29
|
+
it_should_have_input_with_type(:tel)
|
30
|
+
it_should_have_input_with_name("post[phone]")
|
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(:phone))
|
39
|
+
end)
|
40
|
+
end
|
41
|
+
|
42
|
+
it_should_have_input_wrapper_with_id("context2_post_phone_input")
|
43
|
+
it_should_have_label_and_input_with_id("context2_post_phone")
|
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 => :phone, :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,240 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'radio 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 'for belongs_to association' do
|
15
|
+
before do
|
16
|
+
concat(semantic_form_for(@new_post) do |builder|
|
17
|
+
concat(builder.input(:author, :as => :radio, :value_as_class => true, :required => true))
|
18
|
+
end)
|
19
|
+
end
|
20
|
+
|
21
|
+
it_should_have_input_wrapper_with_class("radio")
|
22
|
+
it_should_have_input_wrapper_with_class(:clearfix)
|
23
|
+
it_should_have_input_class_in_the_right_place
|
24
|
+
it_should_have_input_wrapper_with_id("post_author_input")
|
25
|
+
it_should_have_a_nested_div
|
26
|
+
it_should_have_a_nested_div_with_class('choices.input')
|
27
|
+
it_should_have_a_nested_unordered_list_with_class('choices-group.inputs-list')
|
28
|
+
it_should_apply_error_logic_for_input_type(:radio, :block)
|
29
|
+
it_should_use_the_collection_when_provided(:radio, 'input')
|
30
|
+
|
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', /Author/)
|
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 => ::Author.all.size)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should have one option with a "checked" attribute' do
|
46
|
+
output_buffer.should have_tag('form ul input[@checked]', :count => 1)
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "each choice" do
|
50
|
+
|
51
|
+
it 'should not give the choice label the .label class' do
|
52
|
+
output_buffer.should_not have_tag('li.choice label.label')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should not add the required attribute to each input' do
|
56
|
+
output_buffer.should_not have_tag('li.choice input[@required]')
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
it 'should contain a label for the radio input with a nested input and label text' do
|
61
|
+
::Author.all.each do |author|
|
62
|
+
output_buffer.should have_tag('form div.clearfix div.input ul li label', /#{author.to_label}/)
|
63
|
+
output_buffer.should have_tag("form div.clearfix div.input ul li label[@for='post_author_id_#{author.id}']")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should use values as li.class when value_as_class is true' do
|
68
|
+
::Author.all.each do |author|
|
69
|
+
output_buffer.should have_tag("form div.clearfix ul li.author_#{author.id} label")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should have a radio input" do
|
74
|
+
::Author.all.each do |author|
|
75
|
+
output_buffer.should have_tag("form div.clearfix div.input ul li label input#post_author_id_#{author.id}")
|
76
|
+
output_buffer.should have_tag("form div.clearfix div.input ul li label input[@type='radio']")
|
77
|
+
output_buffer.should have_tag("form div.clearfix div.input ul li label input[@value='#{author.id}']")
|
78
|
+
output_buffer.should have_tag("form div.clearfix div.input ul li label input[@name='post[author_id]']")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should mark input as checked if it's the the existing choice" do
|
83
|
+
@new_post.author_id.should == @bob.id
|
84
|
+
@new_post.author.id.should == @bob.id
|
85
|
+
@new_post.author.should == @bob
|
86
|
+
|
87
|
+
concat(semantic_form_for(@new_post) do |builder|
|
88
|
+
concat(builder.input(:author, :as => :radio))
|
89
|
+
end)
|
90
|
+
|
91
|
+
output_buffer.should have_tag("form div.clearfix div.input ul li label input[@checked='checked']")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should mark the input as disabled if options attached for disabling" do
|
95
|
+
concat(semantic_form_for(@new_post) do |builder|
|
96
|
+
concat(builder.input(:author, :as => :radio, :collection => [["Test", 'test'], ["Try", "try", {:disabled => true}]]))
|
97
|
+
end)
|
98
|
+
|
99
|
+
output_buffer.should_not have_tag("form div.clearfix div.input ul li label input[@value='test'][@disabled='disabled']")
|
100
|
+
output_buffer.should have_tag("form div.clearfix div.input ul li label input[@value='try'][@disabled='disabled']")
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should not contain invalid HTML attributes" do
|
104
|
+
|
105
|
+
concat(semantic_form_for(@new_post) do |builder|
|
106
|
+
concat(builder.input(:author, :as => :radio))
|
107
|
+
end)
|
108
|
+
|
109
|
+
output_buffer.should_not have_tag("form div.clearfix div.input ul li input[@find_options]")
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
describe 'and no object is given' do
|
115
|
+
before(:each) do
|
116
|
+
output_buffer.replace ''
|
117
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
118
|
+
concat(builder.input(:author_id, :as => :radio, :collection => ::Author.all))
|
119
|
+
end)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should generate a div with a label' do
|
123
|
+
output_buffer.should have_tag('form div.clearfix label', /Author/)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should generate an li tag for each item in the collection' do
|
127
|
+
output_buffer.should have_tag('form div.clearfix div ul li', :count => ::Author.all.size)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should generate labels for each item' do
|
131
|
+
::Author.all.each do |author|
|
132
|
+
output_buffer.should have_tag('form div div ul li label', /#{author.to_label}/)
|
133
|
+
output_buffer.should have_tag("form div div ul li label[@for='project_author_id_#{author.id}']")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should html escape the label string' do
|
138
|
+
concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
139
|
+
concat(builder.input(:author_id, :as => :radio, :collection => [["<b>Item 1</b>", 1], ["<b>Item 2</b>", 2]]))
|
140
|
+
end)
|
141
|
+
output_buffer.should have_tag('form div div ul li label') do |label|
|
142
|
+
# label.body.should match /<b>Item [12]<\/b>$/
|
143
|
+
label.body.should match /<b>Item [12]<\/b>/
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should generate inputs for each item' do
|
148
|
+
::Author.all.each do |author|
|
149
|
+
output_buffer.should have_tag("form div div ul li label input#project_author_id_#{author.id}")
|
150
|
+
output_buffer.should have_tag("form div div ul li label input[@type='radio']")
|
151
|
+
output_buffer.should have_tag("form div div ul li label input[@value='#{author.id}']")
|
152
|
+
output_buffer.should have_tag("form div div ul li label input[@name='project[author_id]']")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "with i18n of the legend label" do
|
159
|
+
|
160
|
+
before do
|
161
|
+
::I18n.backend.store_translations :en, :formtastic => { :labels => { :post => { :authors => "Translated!" }}}
|
162
|
+
|
163
|
+
with_config :i18n_lookups_by_default, true do
|
164
|
+
@new_post.stub!(:author_ids).and_return(nil)
|
165
|
+
concat(semantic_form_for(@new_post) do |builder|
|
166
|
+
concat(builder.input(:authors, :as => :radio))
|
167
|
+
end)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
after do
|
172
|
+
::I18n.backend.reload!
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should do foo" do
|
176
|
+
output_buffer.should have_tag("div.clearfix > label", /Translated/)
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "when :label option is set" do
|
182
|
+
before do
|
183
|
+
@new_post.stub!(:author_ids).and_return(nil)
|
184
|
+
concat(semantic_form_for(@new_post) do |builder|
|
185
|
+
concat(builder.input(:authors, :as => :radio, :label => 'The authors'))
|
186
|
+
end)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should output the correct label title" do
|
190
|
+
output_buffer.should have_tag("div.clearfix > label", /The authors/)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "when :label option is false" do
|
195
|
+
before do
|
196
|
+
@output_buffer = ''
|
197
|
+
@new_post.stub!(:author_ids).and_return(nil)
|
198
|
+
concat(semantic_form_for(@new_post) do |builder|
|
199
|
+
concat(builder.input(:authors, :as => :radio, :label => false))
|
200
|
+
end)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should not output the legend" do
|
204
|
+
output_buffer.should_not have_tag("legend.label")
|
205
|
+
output_buffer.should_not include(">")
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should not cause escaped HTML" do
|
209
|
+
output_buffer.should_not include(">")
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "when :required option is true" do
|
214
|
+
before do
|
215
|
+
@new_post.stub!(:author_ids).and_return(nil)
|
216
|
+
concat(semantic_form_for(@new_post) do |builder|
|
217
|
+
concat(builder.input(:authors, :as => :radio, :required => true))
|
218
|
+
end)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should output the correct label title" do
|
222
|
+
output_buffer.should have_tag("div.clearfix label abbr")
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "when :namespace is given on form" do
|
227
|
+
before do
|
228
|
+
@output_buffer = ''
|
229
|
+
@new_post.stub!(:author_ids).and_return(nil)
|
230
|
+
concat(semantic_form_for(@new_post, :namespace => "custom_prefix") do |builder|
|
231
|
+
concat(builder.input(:authors, :as => :radio, :label => ''))
|
232
|
+
end)
|
233
|
+
|
234
|
+
output_buffer.should match(/for="custom_prefix_post_author_ids_(\d+)"/)
|
235
|
+
output_buffer.should match(/id="custom_prefix_post_author_ids_(\d+)"/)
|
236
|
+
end
|
237
|
+
it_should_have_input_wrapper_with_id("custom_prefix_post_authors_input")
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
@@ -0,0 +1,479 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
describe 'range input' do
|
6
|
+
|
7
|
+
include FormtasticSpecHelper
|
8
|
+
|
9
|
+
before do
|
10
|
+
@output_buffer = ''
|
11
|
+
mock_everything
|
12
|
+
Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "when object is provided" do
|
16
|
+
before do
|
17
|
+
concat(semantic_form_for(@bob) do |builder|
|
18
|
+
concat(builder.input(:age, :as => :range))
|
19
|
+
end)
|
20
|
+
end
|
21
|
+
|
22
|
+
it_should_have_input_wrapper_with_class(:range)
|
23
|
+
it_should_have_input_wrapper_with_class(:clearfix)
|
24
|
+
it_should_have_input_wrapper_with_class(:stringish) # might be removed
|
25
|
+
it_should_have_input_class_in_the_right_place
|
26
|
+
it_should_have_input_wrapper_with_id("author_age_input")
|
27
|
+
it_should_have_label_with_text(/Age/)
|
28
|
+
it_should_have_label_for("author_age")
|
29
|
+
it_should_have_input_with_id("author_age")
|
30
|
+
it_should_have_input_with_type(:range)
|
31
|
+
it_should_have_input_with_name("author[age]")
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "when namespace is provided" do
|
36
|
+
|
37
|
+
before do
|
38
|
+
concat(semantic_form_for(@james, :namespace => "context2") do |builder|
|
39
|
+
concat(builder.input(:age, :as => :range))
|
40
|
+
end)
|
41
|
+
end
|
42
|
+
|
43
|
+
it_should_have_input_wrapper_with_id("context2_author_age_input")
|
44
|
+
it_should_have_label_and_input_with_id("context2_author_age")
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "when validations require a minimum value (:greater_than)" do
|
49
|
+
before do
|
50
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
51
|
+
active_model_numericality_validator([:title], {:only_integer=>false, :allow_nil=>false, :greater_than=>2})
|
52
|
+
])
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should allow :input_html to override :min" do
|
56
|
+
concat(semantic_form_for(@new_post) do |builder|
|
57
|
+
builder.input(:title, :as => :range, :input_html => { :min => 5 })
|
58
|
+
end)
|
59
|
+
output_buffer.should have_tag('input[@min="5"]')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should allow :input_html to override :min through :in" do
|
63
|
+
concat(semantic_form_for(@new_post) do |builder|
|
64
|
+
builder.input(:title, :as => :range, :input_html => { :in => 5..102 })
|
65
|
+
end)
|
66
|
+
output_buffer.should have_tag('input[@min="5"]')
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should allow options to override :min" do
|
70
|
+
concat(semantic_form_for(@new_post) do |builder|
|
71
|
+
builder.input(:title, :as => :range, :min => 5)
|
72
|
+
end)
|
73
|
+
output_buffer.should have_tag('input[@min="5"]')
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should allow options to override :min through :in" do
|
77
|
+
concat(semantic_form_for(@new_post) do |builder|
|
78
|
+
builder.input(:title, :as => :range, :in => 5..102)
|
79
|
+
end)
|
80
|
+
output_buffer.should have_tag('input[@min="5"]')
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "and the column is an integer" do
|
84
|
+
before do
|
85
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :integer))
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should add a min attribute to the input one greater than the validation" do
|
89
|
+
concat(semantic_form_for(@new_post) do |builder|
|
90
|
+
builder.input(:title, :as => :range)
|
91
|
+
end)
|
92
|
+
output_buffer.should have_tag('input[@min="3"]')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "and the column is a float" do
|
97
|
+
before do
|
98
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :float))
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should raise an error" do
|
102
|
+
lambda {
|
103
|
+
concat(semantic_form_for(@new_post) do |builder|
|
104
|
+
builder.input(:title, :as => :range)
|
105
|
+
end)
|
106
|
+
}.should raise_error(Formtastic::Inputs::Base::Validations::IndeterminableMinimumAttributeError)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "and the column is a big decimal" do
|
111
|
+
before do
|
112
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :decimal))
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should raise an error" do
|
116
|
+
lambda {
|
117
|
+
concat(semantic_form_for(@new_post) do |builder|
|
118
|
+
builder.input(:title, :as => :range)
|
119
|
+
end)
|
120
|
+
}.should raise_error(Formtastic::Inputs::Base::Validations::IndeterminableMinimumAttributeError)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "when validations require a minimum value (:greater_than_or_equal_to)" do
|
127
|
+
before do
|
128
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
129
|
+
active_model_numericality_validator([:title], {:only_integer=>false, :allow_nil=>false, :greater_than_or_equal_to=>2})
|
130
|
+
])
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should allow :input_html to override :min" do
|
134
|
+
concat(semantic_form_for(@new_post) do |builder|
|
135
|
+
builder.input(:title, :as => :range, :input_html => { :min => 5 })
|
136
|
+
end)
|
137
|
+
output_buffer.should have_tag('input[@min="5"]')
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should allow options to override :min" do
|
141
|
+
concat(semantic_form_for(@new_post) do |builder|
|
142
|
+
builder.input(:title, :as => :range, :min => 5)
|
143
|
+
end)
|
144
|
+
output_buffer.should have_tag('input[@min="5"]')
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should allow :input_html to override :min with :in" do
|
148
|
+
concat(semantic_form_for(@new_post) do |builder|
|
149
|
+
builder.input(:title, :as => :range, :input_html => { :in => 5..102 })
|
150
|
+
end)
|
151
|
+
output_buffer.should have_tag('input[@min="5"]')
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should allow options to override :min with :in" do
|
155
|
+
concat(semantic_form_for(@new_post) do |builder|
|
156
|
+
builder.input(:title, :as => :range, :in => 5..102)
|
157
|
+
end)
|
158
|
+
output_buffer.should have_tag('input[@min="5"]')
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
[:integer, :decimal, :float].each do |column_type|
|
163
|
+
describe "and the column is a #{column_type}" do
|
164
|
+
before do
|
165
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => column_type))
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should add a max attribute to the input equal to the validation" do
|
169
|
+
concat(semantic_form_for(@new_post) do |builder|
|
170
|
+
builder.input(:title, :as => :range)
|
171
|
+
end)
|
172
|
+
output_buffer.should have_tag('input[@min="2"]')
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "and there is no column" do
|
178
|
+
before do
|
179
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(nil)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should add a max attribute to the input equal to the validation" do
|
183
|
+
concat(semantic_form_for(@new_post) do |builder|
|
184
|
+
builder.input(:title, :as => :range)
|
185
|
+
end)
|
186
|
+
output_buffer.should have_tag('input[@min="2"]')
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "when validations do not require a minimum value" do
|
192
|
+
|
193
|
+
it "should default to 1" do
|
194
|
+
concat(semantic_form_for(@new_post) do |builder|
|
195
|
+
builder.input(:title, :as => :range)
|
196
|
+
end)
|
197
|
+
output_buffer.should have_tag('input[@min="1"]')
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "when validations require a maximum value (:less_than)" do
|
203
|
+
before do
|
204
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
205
|
+
active_model_numericality_validator([:title], {:only_integer=>false, :allow_nil=>false, :less_than=>20})
|
206
|
+
])
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should allow :input_html to override :max" do
|
210
|
+
concat(semantic_form_for(@new_post) do |builder|
|
211
|
+
builder.input(:title, :as => :range, :input_html => { :max => 102 })
|
212
|
+
end)
|
213
|
+
output_buffer.should have_tag('input[@max="102"]')
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should allow option to override :max" do
|
217
|
+
concat(semantic_form_for(@new_post) do |builder|
|
218
|
+
builder.input(:title, :as => :range, :max => 102)
|
219
|
+
end)
|
220
|
+
output_buffer.should have_tag('input[@max="102"]')
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should allow :input_html to override :max with :in" do
|
224
|
+
concat(semantic_form_for(@new_post) do |builder|
|
225
|
+
builder.input(:title, :as => :range, :input_html => { :in => 1..102 })
|
226
|
+
end)
|
227
|
+
output_buffer.should have_tag('input[@max="102"]')
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should allow option to override :max with :in" do
|
231
|
+
concat(semantic_form_for(@new_post) do |builder|
|
232
|
+
builder.input(:title, :as => :range, :in => 1..102)
|
233
|
+
end)
|
234
|
+
output_buffer.should have_tag('input[@max="102"]')
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "and the column is an integer" do
|
238
|
+
before do
|
239
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :integer))
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should add a max attribute to the input one greater than the validation" do
|
243
|
+
concat(semantic_form_for(@new_post) do |builder|
|
244
|
+
builder.input(:title, :as => :range)
|
245
|
+
end)
|
246
|
+
output_buffer.should have_tag('input[@max="19"]')
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe "and the column is a float" do
|
251
|
+
before do
|
252
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :float))
|
253
|
+
end
|
254
|
+
|
255
|
+
it "should raise an error" do
|
256
|
+
lambda {
|
257
|
+
concat(semantic_form_for(@new_post) do |builder|
|
258
|
+
builder.input(:title, :as => :range)
|
259
|
+
end)
|
260
|
+
}.should raise_error(Formtastic::Inputs::Base::Validations::IndeterminableMaximumAttributeError)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
describe "and the column is a big decimal" do
|
265
|
+
before do
|
266
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :decimal))
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should raise an error" do
|
270
|
+
lambda {
|
271
|
+
concat(semantic_form_for(@new_post) do |builder|
|
272
|
+
builder.input(:title, :as => :range)
|
273
|
+
end)
|
274
|
+
}.should raise_error(Formtastic::Inputs::Base::Validations::IndeterminableMaximumAttributeError)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
describe "when validations require a maximum value (:less_than_or_equal_to)" do
|
281
|
+
before do
|
282
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
283
|
+
active_model_numericality_validator([:title], {:only_integer=>false, :allow_nil=>false, :less_than_or_equal_to=>20})
|
284
|
+
])
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should allow :input_html to override :max" do
|
288
|
+
concat(semantic_form_for(@new_post) do |builder|
|
289
|
+
builder.input(:title, :as => :range, :input_html => { :max => 102 })
|
290
|
+
end)
|
291
|
+
output_buffer.should have_tag('input[@max="102"]')
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should allow options to override :max" do
|
295
|
+
concat(semantic_form_for(@new_post) do |builder|
|
296
|
+
builder.input(:title, :as => :range, :max => 102)
|
297
|
+
end)
|
298
|
+
output_buffer.should have_tag('input[@max="102"]')
|
299
|
+
end
|
300
|
+
|
301
|
+
it "should allow :input_html to override :max with :in" do
|
302
|
+
concat(semantic_form_for(@new_post) do |builder|
|
303
|
+
builder.input(:title, :as => :range, :input_html => { :in => 1..102 })
|
304
|
+
end)
|
305
|
+
output_buffer.should have_tag('input[@max="102"]')
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should allow options to override :max with :in" do
|
309
|
+
concat(semantic_form_for(@new_post) do |builder|
|
310
|
+
builder.input(:title, :as => :range, :in => 1..102)
|
311
|
+
end)
|
312
|
+
output_buffer.should have_tag('input[@max="102"]')
|
313
|
+
end
|
314
|
+
|
315
|
+
[:integer, :decimal, :float].each do |column_type|
|
316
|
+
describe "and the column is a #{column_type}" do
|
317
|
+
before do
|
318
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => column_type))
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should add a max attribute to the input equal to the validation" do
|
322
|
+
concat(semantic_form_for(@new_post) do |builder|
|
323
|
+
builder.input(:title, :as => :range)
|
324
|
+
end)
|
325
|
+
output_buffer.should have_tag('input[@max="20"]')
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
describe "and there is no column" do
|
331
|
+
before do
|
332
|
+
@new_post.stub!(:column_for_attribute).with(:title).and_return(nil)
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should add a max attribute to the input equal to the validation" do
|
336
|
+
concat(semantic_form_for(@new_post) do |builder|
|
337
|
+
builder.input(:title, :as => :range)
|
338
|
+
end)
|
339
|
+
output_buffer.should have_tag('input[@max="20"]')
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "when validations do not require a maximum value" do
|
345
|
+
|
346
|
+
it "should default to 1" do
|
347
|
+
concat(semantic_form_for(@new_post) do |builder|
|
348
|
+
builder.input(:title, :as => :range)
|
349
|
+
end)
|
350
|
+
output_buffer.should have_tag('input[@max="100"]')
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
|
355
|
+
describe "when validations require conflicting minimum values (:greater_than, :greater_than_or_equal_to)" do
|
356
|
+
before do
|
357
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
358
|
+
active_model_numericality_validator([:title], {:only_integer=>false, :allow_nil=>false, :greater_than => 20, :greater_than_or_equal_to=>2})
|
359
|
+
])
|
360
|
+
end
|
361
|
+
|
362
|
+
it "should add a max attribute to the input equal to the :greater_than_or_equal_to validation" do
|
363
|
+
concat(semantic_form_for(@new_post) do |builder|
|
364
|
+
builder.input(:title, :as => :range)
|
365
|
+
end)
|
366
|
+
output_buffer.should have_tag('input[@min="2"]')
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
describe "when validations require conflicting maximum values (:less_than, :less_than_or_equal_to)" do
|
371
|
+
before do
|
372
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
373
|
+
active_model_numericality_validator([:title], {:only_integer=>false, :allow_nil=>false, :less_than => 20, :less_than_or_equal_to=>2})
|
374
|
+
])
|
375
|
+
end
|
376
|
+
|
377
|
+
it "should add a max attribute to the input equal to the :greater_than_or_equal_to validation" do
|
378
|
+
concat(semantic_form_for(@new_post) do |builder|
|
379
|
+
builder.input(:title, :as => :range)
|
380
|
+
end)
|
381
|
+
output_buffer.should have_tag('input[@max="2"]')
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
describe "when validations require only an integer (:only_integer)" do
|
386
|
+
|
387
|
+
before do
|
388
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
389
|
+
active_model_numericality_validator([:title], {:allow_nil=>false, :only_integer=>true})
|
390
|
+
])
|
391
|
+
end
|
392
|
+
|
393
|
+
it "should add a step=1 attribute to the input to signify that only whole numbers are allowed" do
|
394
|
+
concat(semantic_form_for(@new_post) do |builder|
|
395
|
+
builder.input(:title, :as => :range)
|
396
|
+
end)
|
397
|
+
output_buffer.should have_tag('input[@step="1"]')
|
398
|
+
end
|
399
|
+
|
400
|
+
it "should let input_html override :step" do
|
401
|
+
concat(semantic_form_for(@new_post) do |builder|
|
402
|
+
builder.input(:title, :as => :range, :input_html => { :step => 3 })
|
403
|
+
end)
|
404
|
+
output_buffer.should have_tag('input[@step="3"]')
|
405
|
+
end
|
406
|
+
|
407
|
+
it "should let options override :step" do
|
408
|
+
concat(semantic_form_for(@new_post) do |builder|
|
409
|
+
builder.input(:title, :as => :range, :step => 3)
|
410
|
+
end)
|
411
|
+
output_buffer.should have_tag('input[@step="3"]')
|
412
|
+
end
|
413
|
+
|
414
|
+
end
|
415
|
+
|
416
|
+
describe "when validations require a :step (non standard)" do
|
417
|
+
|
418
|
+
before do
|
419
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
420
|
+
active_model_numericality_validator([:title], {:allow_nil=>false, :only_integer=>true, :step=>2})
|
421
|
+
])
|
422
|
+
end
|
423
|
+
|
424
|
+
it "should add a step=1 attribute to the input to signify that only whole numbers are allowed" do
|
425
|
+
concat(semantic_form_for(@new_post) do |builder|
|
426
|
+
builder.input(:title, :as => :range)
|
427
|
+
end)
|
428
|
+
output_buffer.should have_tag('input[@step="2"]')
|
429
|
+
end
|
430
|
+
|
431
|
+
it "should let input_html override :step" do
|
432
|
+
concat(semantic_form_for(@new_post) do |builder|
|
433
|
+
builder.input(:title, :as => :range, :input_html => { :step => 3 })
|
434
|
+
end)
|
435
|
+
output_buffer.should have_tag('input[@step="3"]')
|
436
|
+
end
|
437
|
+
|
438
|
+
it "should let options override :step" do
|
439
|
+
concat(semantic_form_for(@new_post) do |builder|
|
440
|
+
builder.input(:title, :as => :range, :step => 3)
|
441
|
+
end)
|
442
|
+
output_buffer.should have_tag('input[@step="3"]')
|
443
|
+
end
|
444
|
+
|
445
|
+
end
|
446
|
+
|
447
|
+
describe "when validations do not specify :step (non standard) or :only_integer" do
|
448
|
+
|
449
|
+
before do
|
450
|
+
@new_post.class.stub!(:validators_on).with(:title).and_return([
|
451
|
+
active_model_numericality_validator([:title], {:allow_nil=>false})
|
452
|
+
])
|
453
|
+
end
|
454
|
+
|
455
|
+
it "should default step to 1" do
|
456
|
+
concat(semantic_form_for(@new_post) do |builder|
|
457
|
+
builder.input(:title, :as => :range)
|
458
|
+
end)
|
459
|
+
output_buffer.should have_tag('input[@step="1"]')
|
460
|
+
end
|
461
|
+
|
462
|
+
it "should let input_html set :step" do
|
463
|
+
concat(semantic_form_for(@new_post) do |builder|
|
464
|
+
builder.input(:title, :as => :range, :input_html => { :step => 3 })
|
465
|
+
end)
|
466
|
+
output_buffer.should have_tag('input[@step="3"]')
|
467
|
+
end
|
468
|
+
|
469
|
+
it "should let options set :step" do
|
470
|
+
concat(semantic_form_for(@new_post) do |builder|
|
471
|
+
builder.input(:title, :as => :range, :step => 3)
|
472
|
+
end)
|
473
|
+
output_buffer.should have_tag('input[@step="3"]')
|
474
|
+
end
|
475
|
+
|
476
|
+
end
|
477
|
+
|
478
|
+
end
|
479
|
+
|