formtastic-bootstrap 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +123 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +159 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/formtastic-bootstrap.gemspec +128 -0
  10. data/lib/action_view/helpers/text_field_date_helper.rb +166 -0
  11. data/lib/formtastic-bootstrap.rb +5 -0
  12. data/lib/formtastic-bootstrap/form_builder.rb +38 -0
  13. data/lib/formtastic-bootstrap/helpers.rb +19 -0
  14. data/lib/formtastic-bootstrap/helpers/buttons_helper.rb +47 -0
  15. data/lib/formtastic-bootstrap/helpers/fieldset_wrapper.rb +37 -0
  16. data/lib/formtastic-bootstrap/helpers/input_helper.rb +12 -0
  17. data/lib/formtastic-bootstrap/helpers/inputs_helper.rb +36 -0
  18. data/lib/formtastic-bootstrap/inputs.rb +28 -0
  19. data/lib/formtastic-bootstrap/inputs/base.rb +22 -0
  20. data/lib/formtastic-bootstrap/inputs/base/choices.rb +49 -0
  21. data/lib/formtastic-bootstrap/inputs/base/errors.rb +48 -0
  22. data/lib/formtastic-bootstrap/inputs/base/hints.rb +27 -0
  23. data/lib/formtastic-bootstrap/inputs/base/html.rb +21 -0
  24. data/lib/formtastic-bootstrap/inputs/base/labelling.rb +18 -0
  25. data/lib/formtastic-bootstrap/inputs/base/stringish.rb +18 -0
  26. data/lib/formtastic-bootstrap/inputs/base/timeish.rb +35 -0
  27. data/lib/formtastic-bootstrap/inputs/base/wrapping.rb +56 -0
  28. data/lib/formtastic-bootstrap/inputs/boolean_input.rb +33 -0
  29. data/lib/formtastic-bootstrap/inputs/check_boxes_input.rb +35 -0
  30. data/lib/formtastic-bootstrap/inputs/date_input.rb +16 -0
  31. data/lib/formtastic-bootstrap/inputs/datetime_input.rb +19 -0
  32. data/lib/formtastic-bootstrap/inputs/email_input.rb +15 -0
  33. data/lib/formtastic-bootstrap/inputs/file_input.rb +14 -0
  34. data/lib/formtastic-bootstrap/inputs/hidden_input.rb +12 -0
  35. data/lib/formtastic-bootstrap/inputs/number_input.rb +15 -0
  36. data/lib/formtastic-bootstrap/inputs/password_input.rb +15 -0
  37. data/lib/formtastic-bootstrap/inputs/phone_input.rb +15 -0
  38. data/lib/formtastic-bootstrap/inputs/radio_input.rb +32 -0
  39. data/lib/formtastic-bootstrap/inputs/range_input.rb +15 -0
  40. data/lib/formtastic-bootstrap/inputs/search_input.rb +15 -0
  41. data/lib/formtastic-bootstrap/inputs/select_input.rb +14 -0
  42. data/lib/formtastic-bootstrap/inputs/string_input.rb +15 -0
  43. data/lib/formtastic-bootstrap/inputs/text_input.rb +14 -0
  44. data/lib/formtastic-bootstrap/inputs/time_input.rb +16 -0
  45. data/lib/formtastic-bootstrap/inputs/url_input.rb +14 -0
  46. data/spec/builder/errors_spec.rb +214 -0
  47. data/spec/builder/semantic_fields_for_spec.rb +130 -0
  48. data/spec/helpers/input_helper_spec.rb +956 -0
  49. data/spec/helpers/inputs_helper_spec.rb +577 -0
  50. data/spec/inputs/boolean_input_spec.rb +193 -0
  51. data/spec/inputs/check_boxes_input_spec.rb +439 -0
  52. data/spec/inputs/date_input_spec.rb +147 -0
  53. data/spec/inputs/datetime_input_spec.rb +101 -0
  54. data/spec/inputs/email_input_spec.rb +59 -0
  55. data/spec/inputs/file_input_spec.rb +63 -0
  56. data/spec/inputs/hidden_input_spec.rb +122 -0
  57. data/spec/inputs/number_input_spec.rb +787 -0
  58. data/spec/inputs/password_input_spec.rb +73 -0
  59. data/spec/inputs/phone_input_spec.rb +59 -0
  60. data/spec/inputs/radio_input_spec.rb +240 -0
  61. data/spec/inputs/range_input_spec.rb +479 -0
  62. data/spec/inputs/search_input_spec.rb +59 -0
  63. data/spec/inputs/select_input_spec.rb +567 -0
  64. data/spec/inputs/string_input_spec.rb +182 -0
  65. data/spec/inputs/text_input_spec.rb +163 -0
  66. data/spec/inputs/time_input_spec.rb +206 -0
  67. data/spec/inputs/url_input_spec.rb +59 -0
  68. data/spec/spec_helper.rb +24 -0
  69. data/spec/support/custom_macros.rb +704 -0
  70. data/spec/support/depracation.rb +6 -0
  71. data/spec/support/formtastic_spec_helper.rb +382 -0
  72. metadata +204 -0
@@ -0,0 +1,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 /&lt;b&gt;Item [12]&lt;\/b&gt;$/
143
+ label.body.should match /&lt;b&gt;Item [12]&lt;\/b&gt;/
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("&gt;")
206
+ end
207
+
208
+ it "should not cause escaped HTML" do
209
+ output_buffer.should_not include("&gt;")
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
+