formtastic-bootstrap 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/README.md +11 -2
  2. data/VERSION +1 -1
  3. data/vendor/assets/stylesheets/formtastic-bootstrap.css +4 -0
  4. metadata +51 -154
  5. data/.rspec +0 -1
  6. data/Gemfile +0 -14
  7. data/Gemfile.lock +0 -131
  8. data/Rakefile +0 -49
  9. data/formtastic-bootstrap.gemspec +0 -166
  10. data/lib/action_view/helpers/text_field_date_helper.rb +0 -166
  11. data/lib/formtastic-bootstrap/actions.rb +0 -10
  12. data/lib/formtastic-bootstrap/actions/base.rb +0 -22
  13. data/lib/formtastic-bootstrap/actions/button_action.rb +0 -13
  14. data/lib/formtastic-bootstrap/actions/input_action.rb +0 -13
  15. data/lib/formtastic-bootstrap/actions/link_action.rb +0 -12
  16. data/lib/formtastic-bootstrap/engine.rb +0 -4
  17. data/lib/formtastic-bootstrap/form_builder.rb +0 -40
  18. data/lib/formtastic-bootstrap/helpers.rb +0 -17
  19. data/lib/formtastic-bootstrap/helpers/action_helper.rb +0 -12
  20. data/lib/formtastic-bootstrap/helpers/actions_helper.rb +0 -24
  21. data/lib/formtastic-bootstrap/helpers/fieldset_wrapper.rb +0 -35
  22. data/lib/formtastic-bootstrap/helpers/input_helper.rb +0 -12
  23. data/lib/formtastic-bootstrap/helpers/inputs_helper.rb +0 -34
  24. data/lib/formtastic-bootstrap/inputs.rb +0 -36
  25. data/lib/formtastic-bootstrap/inputs/base.rb +0 -45
  26. data/lib/formtastic-bootstrap/inputs/base/choices.rb +0 -20
  27. data/lib/formtastic-bootstrap/inputs/base/collections.rb +0 -9
  28. data/lib/formtastic-bootstrap/inputs/base/errors.rb +0 -48
  29. data/lib/formtastic-bootstrap/inputs/base/grouped_collections.rb +0 -9
  30. data/lib/formtastic-bootstrap/inputs/base/hints.rb +0 -27
  31. data/lib/formtastic-bootstrap/inputs/base/html.rb +0 -21
  32. data/lib/formtastic-bootstrap/inputs/base/labelling.rb +0 -29
  33. data/lib/formtastic-bootstrap/inputs/base/numeric.rb +0 -9
  34. data/lib/formtastic-bootstrap/inputs/base/stringish.rb +0 -17
  35. data/lib/formtastic-bootstrap/inputs/base/timeish.rb +0 -55
  36. data/lib/formtastic-bootstrap/inputs/base/wrapping.rb +0 -55
  37. data/lib/formtastic-bootstrap/inputs/boolean_input.rb +0 -29
  38. data/lib/formtastic-bootstrap/inputs/check_boxes_input.rb +0 -40
  39. data/lib/formtastic-bootstrap/inputs/date_input.rb +0 -10
  40. data/lib/formtastic-bootstrap/inputs/date_select_input.rb +0 -8
  41. data/lib/formtastic-bootstrap/inputs/datetime_input.rb +0 -10
  42. data/lib/formtastic-bootstrap/inputs/datetime_select_input.rb +0 -8
  43. data/lib/formtastic-bootstrap/inputs/email_input.rb +0 -15
  44. data/lib/formtastic-bootstrap/inputs/file_input.rb +0 -14
  45. data/lib/formtastic-bootstrap/inputs/hidden_input.rb +0 -12
  46. data/lib/formtastic-bootstrap/inputs/number_input.rb +0 -15
  47. data/lib/formtastic-bootstrap/inputs/password_input.rb +0 -15
  48. data/lib/formtastic-bootstrap/inputs/phone_input.rb +0 -15
  49. data/lib/formtastic-bootstrap/inputs/radio_input.rb +0 -46
  50. data/lib/formtastic-bootstrap/inputs/range_input.rb +0 -15
  51. data/lib/formtastic-bootstrap/inputs/search_input.rb +0 -15
  52. data/lib/formtastic-bootstrap/inputs/select_input.rb +0 -16
  53. data/lib/formtastic-bootstrap/inputs/string_input.rb +0 -8
  54. data/lib/formtastic-bootstrap/inputs/text_input.rb +0 -14
  55. data/lib/formtastic-bootstrap/inputs/time_input.rb +0 -10
  56. data/lib/formtastic-bootstrap/inputs/time_select_input.rb +0 -8
  57. data/lib/formtastic-bootstrap/inputs/time_zone_input.rb +0 -14
  58. data/lib/formtastic-bootstrap/inputs/url_input.rb +0 -14
  59. data/spec/actions/button_action_spec.rb +0 -63
  60. data/spec/actions/input_action_spec.rb +0 -59
  61. data/spec/actions/link_action_spec.rb +0 -92
  62. data/spec/builder/semantic_fields_for_spec.rb +0 -130
  63. data/spec/helpers/action_helper_spec.rb +0 -368
  64. data/spec/helpers/actions_helper_spec.rb +0 -147
  65. data/spec/helpers/input_helper_spec.rb +0 -935
  66. data/spec/helpers/inputs_helper_spec.rb +0 -636
  67. data/spec/inputs/boolean_input_spec.rb +0 -226
  68. data/spec/inputs/check_boxes_input_spec.rb +0 -454
  69. data/spec/inputs/date_select_input_spec.rb +0 -164
  70. data/spec/inputs/datetime_select_input_spec.rb +0 -112
  71. data/spec/inputs/deprecated_time_date_datetime_inputs_spec.rb +0 -48
  72. data/spec/inputs/email_input_spec.rb +0 -86
  73. data/spec/inputs/file_input_spec.rb +0 -90
  74. data/spec/inputs/hidden_input_spec.rb +0 -153
  75. data/spec/inputs/number_input_spec.rb +0 -816
  76. data/spec/inputs/password_input_spec.rb +0 -100
  77. data/spec/inputs/phone_input_spec.rb +0 -86
  78. data/spec/inputs/radio_input_spec.rb +0 -267
  79. data/spec/inputs/range_input_spec.rb +0 -506
  80. data/spec/inputs/search_input_spec.rb +0 -85
  81. data/spec/inputs/select_input_spec.rb +0 -624
  82. data/spec/inputs/string_input_spec.rb +0 -210
  83. data/spec/inputs/text_input_spec.rb +0 -188
  84. data/spec/inputs/time_select_input_spec.rb +0 -191
  85. data/spec/inputs/time_zone_input_spec.rb +0 -118
  86. data/spec/inputs/url_input_spec.rb +0 -86
  87. data/spec/spec_helper.rb +0 -30
  88. data/spec/support/custom_macros.rb +0 -537
  89. data/spec/support/fb_custom_macros.rb +0 -23
@@ -1,147 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- describe 'FormtasticBootstrap::FormBuilder#actions' do
5
-
6
- include FormtasticSpecHelper
7
-
8
- before do
9
- @output_buffer = ''
10
- mock_everything
11
- end
12
-
13
- describe 'with a block' do
14
- describe 'when no options are provided' do
15
- before do
16
- concat(semantic_form_for(@new_post) do |builder|
17
- concat(builder.actions do
18
- concat('hello')
19
- end)
20
- end)
21
- end
22
-
23
- it 'should render a fieldset inside the form, with a class of "actions"' do
24
- output_buffer.should have_tag("form fieldset.form-actions")
25
- end
26
-
27
- it 'should not render an ol inside the fieldset' do
28
- output_buffer.should_not have_tag("form fieldset.form-actions ol")
29
- end
30
-
31
- it 'should render the contents of the block inside the fieldset' do
32
- output_buffer.should have_tag("form fieldset.form-actions", /hello/)
33
- end
34
-
35
- it 'should not render a legend inside the fieldset' do
36
- output_buffer.should_not have_tag("form fieldset.form-actions legend")
37
- end
38
- end
39
-
40
- describe 'when a :name option is provided' do
41
- before do
42
- @legend_text = "Advanced options"
43
-
44
- concat(semantic_form_for(@new_post) do |builder|
45
- builder.actions :name => @legend_text do
46
- end
47
- end)
48
- end
49
- it 'should render a fieldset inside the form' do
50
- output_buffer.should have_tag("form fieldset.form-actions legend", /#{@legend_text}/)
51
- end
52
- end
53
-
54
- describe 'when other options are provided' do
55
- before do
56
- @id_option = 'advanced'
57
- @class_option = 'wide'
58
-
59
- concat(semantic_form_for(@new_post) do |builder|
60
- builder.actions :id => @id_option, :class => @class_option do
61
- end
62
- end)
63
- end
64
- it 'should pass the options into the fieldset tag as attributes' do
65
- output_buffer.should have_tag("form fieldset##{@id_option}")
66
- output_buffer.should have_tag("form fieldset.#{@class_option}")
67
- end
68
- end
69
-
70
- end
71
-
72
- describe 'without a block' do
73
-
74
- describe 'with no args (default buttons)' do
75
-
76
- before do
77
- concat(semantic_form_for(@new_post) do |builder|
78
- concat(builder.actions)
79
- end)
80
- end
81
-
82
- it 'should render a form' do
83
- output_buffer.should have_tag('form')
84
- end
85
-
86
- it 'should render an actions fieldset inside the form' do
87
- output_buffer.should have_tag('form fieldset.form-actions')
88
- end
89
-
90
- it 'should not render a legend in the fieldset' do
91
- output_buffer.should_not have_tag('form fieldset.form-actions legend')
92
- end
93
-
94
- it 'should not render an ol in the fieldset' do
95
- output_buffer.should_not have_tag('form fieldset.form-actions ol')
96
- end
97
-
98
- it 'should render a button in the fieldset for each default action' do
99
- output_buffer.should have_tag('form fieldset.form-actions input.btn', :count => 1)
100
- end
101
-
102
- end
103
-
104
- describe 'with button names as args' do
105
-
106
- before do
107
- concat(semantic_form_for(@new_post) do |builder|
108
- concat(builder.actions(:submit, :cancel, :reset))
109
- end)
110
- end
111
-
112
- it 'should not render a form with a fieldset containing a list item for each button arg' do
113
- output_buffer.should_not have_tag('form > fieldset.form-actions > ol > li.action', :count => 3)
114
- end
115
-
116
- it 'should render a form with a fieldset containing each button arg' do
117
- output_buffer.should_not have_tag('form > fieldset.form-actions > input.btn', :count => 3)
118
- end
119
-
120
- end
121
-
122
- describe 'with button names as args and an options hash' do
123
-
124
- before do
125
- concat(semantic_form_for(@new_post) do |builder|
126
- concat(builder.actions(:submit, :cancel, :reset, :name => "Now click a button", :id => "my-id"))
127
- end)
128
- end
129
-
130
- it 'should render a form with a fieldset containing each button arg' do
131
- output_buffer.should have_tag('form > fieldset.form-actions > .btn', :count => 3)
132
- end
133
-
134
- it 'should pass the options down to the fieldset' do
135
- output_buffer.should have_tag('form > fieldset#my-id.form-actions')
136
- end
137
-
138
- it 'should use the special :name option as a text for the legend tag' do
139
- output_buffer.should have_tag('form > fieldset#my-id.form-actions > legend', /Now click a button/)
140
- end
141
-
142
- end
143
-
144
- end
145
-
146
- end
147
-
@@ -1,935 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
-
4
- describe 'FormtasticBootstrap::FormBuilder#input' do
5
-
6
- include FormtasticSpecHelper
7
-
8
- before do
9
- @output_buffer = ''
10
- mock_everything
11
-
12
- @errors = mock('errors')
13
- @errors.stub!(:[]).and_return([])
14
- @new_post.stub!(:errors).and_return(@errors)
15
- end
16
-
17
- after do
18
- ::I18n.backend.reload!
19
- end
20
-
21
- describe 'arguments and options' do
22
-
23
- it 'should require the first argument (the method on form\'s object)' do
24
- lambda {
25
- concat(semantic_form_for(@new_post) do |builder|
26
- concat(builder.input()) # no args passed in at all
27
- end)
28
- }.should raise_error(ArgumentError)
29
- end
30
-
31
- describe ':required option' do
32
-
33
- describe 'when true' do
34
-
35
- it 'should set a "required" class' do
36
- with_config :required_string, " required yo!" do
37
- concat(semantic_form_for(@new_post) do |builder|
38
- concat(builder.input(:title, :required => true))
39
- end)
40
- output_buffer.should_not have_tag('form div.optional')
41
- output_buffer.should have_tag('form div.required')
42
- end
43
- end
44
-
45
- it 'should append the "required" string to the label' do
46
- with_config :required_string, " required yo!" do
47
- concat(semantic_form_for(@new_post) do |builder|
48
- concat(builder.input(:title, :required => true))
49
- end)
50
- output_buffer.should have_tag('form div.required label', /required yo/)
51
- end
52
- end
53
- end
54
-
55
- describe 'when false' do
56
-
57
- before do
58
- @string = Formtastic::FormBuilder.optional_string = " optional yo!" # ensure there's something in the string
59
- @new_post.class.should_not_receive(:reflect_on_all_validations)
60
- end
61
-
62
- after do
63
- Formtastic::FormBuilder.optional_string = ''
64
- end
65
-
66
- it 'should set an "optional" class' do
67
- concat(semantic_form_for(@new_post) do |builder|
68
- concat(builder.input(:title, :required => false))
69
- end)
70
- output_buffer.should_not have_tag('form div.required')
71
- output_buffer.should have_tag('form div.optional')
72
- end
73
-
74
- it 'should set and "optional" class also when there is presence validator' do
75
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
76
- active_model_presence_validator([:title])
77
- ])
78
- concat(semantic_form_for(@new_post) do |builder|
79
- concat(builder.input(:title, :required => false))
80
- end)
81
- output_buffer.should_not have_tag('form div.required')
82
- output_buffer.should have_tag('form div.optional')
83
- end
84
-
85
- it 'should append the "optional" string to the label' do
86
- concat(semantic_form_for(@new_post) do |builder|
87
- concat(builder.input(:title, :required => false))
88
- end)
89
- output_buffer.should have_tag('form div.optional label', /#{@string}$/)
90
- end
91
-
92
- end
93
-
94
- describe 'when not provided' do
95
-
96
- describe 'and an object was not given' do
97
-
98
- it 'should use the default value' do
99
- Formtastic::FormBuilder.all_fields_required_by_default.should == true
100
- Formtastic::FormBuilder.all_fields_required_by_default = false
101
-
102
- concat(semantic_form_for(:project, :url => 'http://test.host/') do |builder|
103
- concat(builder.input(:title))
104
- end)
105
- output_buffer.should_not have_tag('form div.required')
106
- output_buffer.should have_tag('form div.optional')
107
-
108
- Formtastic::FormBuilder.all_fields_required_by_default = true
109
- end
110
-
111
- end
112
-
113
- describe 'and an object with :validators_on was given (ActiveModel, Active Resource)' do
114
- before do
115
- @new_post.stub!(:class).and_return(::PostModel)
116
- end
117
-
118
- after do
119
- @new_post.stub!(:class).and_return(::Post)
120
- end
121
- describe 'and validates_presence_of was called for the method' do
122
- it 'should be required' do
123
-
124
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
125
- active_model_presence_validator([:title])
126
- ])
127
-
128
- @new_post.class.should_receive(:validators_on).with(:body).any_number_of_times.and_return([
129
- active_model_presence_validator([:body], {:if => true})
130
- ])
131
-
132
- concat(semantic_form_for(@new_post) do |builder|
133
- concat(builder.input(:title))
134
- concat(builder.input(:body))
135
- end)
136
- output_buffer.should have_tag('form div.required')
137
- output_buffer.should_not have_tag('form div.optional')
138
- end
139
-
140
- it 'should be required when there is :on => :create option on create' do
141
- with_config :required_string, " required yo!" do
142
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
143
- active_model_presence_validator([:title], {:on => :create})
144
- ])
145
- concat(semantic_form_for(@new_post) do |builder|
146
- concat(builder.input(:title))
147
- end)
148
- output_buffer.should have_tag('form div.required')
149
- output_buffer.should_not have_tag('form div.optional')
150
- end
151
- end
152
-
153
- it 'should be required when there is :on => :save option on create' do
154
- with_config :required_string, " required yo!" do
155
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
156
- active_model_presence_validator([:title], {:on => :save})
157
- ])
158
- concat(semantic_form_for(@new_post) do |builder|
159
- concat(builder.input(:title))
160
- end)
161
- output_buffer.should have_tag('form div.required')
162
- output_buffer.should_not have_tag('form div.optional')
163
- end
164
- end
165
-
166
- it 'should be required when there is :on => :save option on update' do
167
- with_config :required_string, " required yo!" do
168
- @fred.class.should_receive(:validators_on).with(:login).any_number_of_times.and_return([
169
- active_model_presence_validator([:login], {:on => :save})
170
- ])
171
- concat(semantic_form_for(@fred) do |builder|
172
- concat(builder.input(:login))
173
- end)
174
- output_buffer.should have_tag('form div.required')
175
- output_buffer.should_not have_tag('form div.optional')
176
- end
177
- end
178
-
179
- it 'should not be required when there is :on => :create option on update' do
180
- @fred.class.should_receive(:validators_on).with(:login).any_number_of_times.and_return([
181
- active_model_presence_validator([:login], {:on => :create})
182
- ])
183
- concat(semantic_form_for(@fred) do |builder|
184
- concat(builder.input(:login))
185
- end)
186
- output_buffer.should_not have_tag('form div.required')
187
- output_buffer.should have_tag('form div.optional')
188
- end
189
-
190
- it 'should not be required when there is :on => :update option on create' do
191
- @new_post.class.should_receive(:validators_on).with(:title).any_number_of_times.and_return([
192
- active_model_presence_validator([:title], {:on => :update})
193
- ])
194
- concat(semantic_form_for(@new_post) do |builder|
195
- concat(builder.input(:title))
196
- end)
197
- output_buffer.should_not have_tag('form div.required')
198
- output_buffer.should have_tag('form div.optional')
199
- end
200
-
201
- it 'should be not be required if the optional :if condition is not satisifed' do
202
- presence_should_be_required(:required => false, :tag => :body, :options => { :if => false })
203
- end
204
-
205
- it 'should not be required if the optional :if proc evaluates to false' do
206
- presence_should_be_required(:required => false, :tag => :body, :options => { :if => proc { |record| false } })
207
- end
208
-
209
- it 'should be required if the optional :if proc evaluates to true' do
210
- presence_should_be_required(:required => true, :tag => :body, :options => { :if => proc { |record| true } })
211
- end
212
-
213
- it 'should not be required if the optional :unless proc evaluates to true' do
214
- presence_should_be_required(:required => false, :tag => :body, :options => { :unless => proc { |record| true } })
215
- end
216
-
217
- it 'should be required if the optional :unless proc evaluates to false' do
218
- presence_should_be_required(:required => true, :tag => :body, :options => { :unless => proc { |record| false } })
219
- end
220
-
221
- it 'should be required if the optional :if with a method string evaluates to true' do
222
- @new_post.should_receive(:required_condition).and_return(true)
223
- presence_should_be_required(:required => true, :tag => :body, :options => { :if => :required_condition })
224
- end
225
-
226
- it 'should be required if the optional :if with a method string evaluates to false' do
227
- @new_post.should_receive(:required_condition).and_return(false)
228
- presence_should_be_required(:required => false, :tag => :body, :options => { :if => :required_condition })
229
- end
230
-
231
- it 'should be required if the optional :unless with a method string evaluates to false' do
232
- @new_post.should_receive(:required_condition).and_return(false)
233
- presence_should_be_required(:required => true, :tag => :body, :options => { :unless => :required_condition })
234
- end
235
-
236
- it 'should not be required if the optional :unless with a method string evaluates to true' do
237
- @new_post.should_receive(:required_condition).and_return(true)
238
- presence_should_be_required(:required => false, :tag => :body, :options => { :unless => :required_condition })
239
- end
240
- end
241
-
242
- describe 'and validates_inclusion_of was called for the method' do
243
- it 'should be required' do
244
- @new_post.class.should_receive(:validators_on).with(:published).any_number_of_times.and_return([
245
- active_model_inclusion_validator([:published], {:in => [false, true]})
246
- ])
247
- should_be_required(:tag => :published, :required => true)
248
- end
249
-
250
- it 'should not be required if allow_blank is true' do
251
- @new_post.class.should_receive(:validators_on).with(:published).any_number_of_times.and_return([
252
- active_model_inclusion_validator([:published], {:in => [false, true], :allow_blank => true})
253
- ])
254
- should_be_required(:tag => :published, :required => false)
255
- end
256
- end
257
-
258
- describe 'and validates_length_of was called for the method' do
259
- it 'should be required if minimum is set' do
260
- length_should_be_required(:tag => :title, :required => true, :options => {:minimum => 1})
261
- end
262
-
263
- it 'should be required if :within is set' do
264
- length_should_be_required(:tag => :title, :required => true, :options => {:within => 1..5})
265
- end
266
-
267
- it 'should not be required if :within allows zero length' do
268
- length_should_be_required(:tag => :title, :required => false, :options => {:within => 0..5})
269
- end
270
-
271
- it 'should not be required if only :minimum is zero' do
272
- length_should_be_required(:tag => :title, :required => false, :options => {:minimum => 0})
273
- end
274
-
275
- it 'should not be required if only :minimum is not set' do
276
- length_should_be_required(:tag => :title, :required => false, :options => {:maximum => 5})
277
- end
278
-
279
- it 'should not be required if allow_blank is true' do
280
- length_should_be_required(:tag => :published, :required => false, :options => {:allow_blank => true})
281
- end
282
- end
283
-
284
- def add_presence_validator(options)
285
- @new_post.class.stub!(:validators_on).with(options[:tag]).and_return([
286
- active_model_presence_validator([options[:tag]], options[:options])
287
- ])
288
- end
289
-
290
- def add_length_validator(options)
291
- @new_post.class.should_receive(:validators_on).with(options[:tag]).any_number_of_times {[
292
- active_model_length_validator([options[:tag]], options[:options])
293
- ]}
294
- end
295
-
296
- # TODO make a matcher for this?
297
- def should_be_required(options)
298
- concat(semantic_form_for(@new_post) do |builder|
299
- concat(builder.input(options[:tag]))
300
- end)
301
-
302
- if options[:required]
303
- output_buffer.should_not have_tag('form div.optional')
304
- output_buffer.should have_tag('form div.required')
305
- else
306
- output_buffer.should have_tag('form div.optional')
307
- output_buffer.should_not have_tag('form div.required')
308
- end
309
- end
310
-
311
- def presence_should_be_required(options)
312
- add_presence_validator(options)
313
- should_be_required(options)
314
- end
315
-
316
- def length_should_be_required(options)
317
- add_length_validator(options)
318
- should_be_required(options)
319
- end
320
-
321
- # TODO JF reversed this during refactor, need to make sure
322
- describe 'and there are no requirement validations on the method' do
323
- before do
324
- @new_post.class.should_receive(:validators_on).with(:title).and_return([])
325
- end
326
-
327
- it 'should not be required' do
328
- concat(semantic_form_for(@new_post) do |builder|
329
- concat(builder.input(:title))
330
- end)
331
- output_buffer.should_not have_tag('form div.required')
332
- output_buffer.should have_tag('form div.optional')
333
- end
334
- end
335
-
336
- end
337
-
338
- describe 'and an object without :validators_on' do
339
-
340
- it 'should use the default value' do
341
- Formtastic::FormBuilder.all_fields_required_by_default.should == true
342
- Formtastic::FormBuilder.all_fields_required_by_default = false
343
-
344
- concat(semantic_form_for(@new_post) do |builder|
345
- concat(builder.input(:title))
346
- end)
347
- output_buffer.should_not have_tag('form div.required')
348
- output_buffer.should have_tag('form div.optional')
349
-
350
- Formtastic::FormBuilder.all_fields_required_by_default = true
351
- end
352
-
353
- end
354
-
355
- end
356
-
357
- end
358
-
359
- describe ':as option' do
360
-
361
- describe 'when not provided' do
362
-
363
- it 'should default to a string for forms without objects unless column is password' do
364
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
365
- concat(builder.input(:anything))
366
- end)
367
- output_buffer.should have_tag('form div.string')
368
- end
369
-
370
- it 'should default to password for forms without objects if column is password' do
371
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
372
- concat(builder.input(:password))
373
- concat(builder.input(:password_confirmation))
374
- concat(builder.input(:confirm_password))
375
- end)
376
- output_buffer.should have_tag('form div.password', :count => 3)
377
- end
378
-
379
- it 'should default to a string for methods on objects that don\'t respond to "column_for_attribute"' do
380
- @new_post.stub!(:method_without_a_database_column)
381
- @new_post.stub!(:column_for_attribute).and_return(nil)
382
- default_input_type(nil, :method_without_a_database_column).should == :string
383
- end
384
-
385
- it 'should default to :password for methods that don\'t have a column in the database but "password" is in the method name' do
386
- @new_post.stub!(:password_method_without_a_database_column)
387
- @new_post.stub!(:column_for_attribute).and_return(nil)
388
- default_input_type(nil, :password_method_without_a_database_column).should == :password
389
- end
390
-
391
- it 'should default to :password for methods on objects that don\'t respond to "column_for_attribute" but "password" is in the method name' do
392
- @new_post.stub!(:password_method_without_a_database_column)
393
- @new_post.stub!(:column_for_attribute).and_return(nil)
394
- default_input_type(nil, :password_method_without_a_database_column).should == :password
395
- end
396
-
397
- it 'should default to :number for "integer" column with name ending in "_id"' do
398
- @new_post.stub!(:aws_instance_id)
399
- @new_post.stub!(:column_for_attribute).with(:aws_instance_id).and_return(mock('column', :type => :integer))
400
- default_input_type(:integer, :aws_instance_id).should == :number
401
- end
402
-
403
- it 'should default to :select for associations' do
404
- @new_post.class.stub!(:reflect_on_association).with(:user_id).and_return(mock('ActiveRecord::Reflection::AssociationReflection'))
405
- @new_post.class.stub!(:reflect_on_association).with(:section_id).and_return(mock('ActiveRecord::Reflection::AssociationReflection'))
406
- default_input_type(:integer, :user_id).should == :select
407
- default_input_type(:integer, :section_id).should == :select
408
- end
409
-
410
- it 'should default to :password for :string column types with "password" in the method name' do
411
- default_input_type(:string, :password).should == :password
412
- default_input_type(:string, :hashed_password).should == :password
413
- default_input_type(:string, :password_hash).should == :password
414
- end
415
-
416
- it 'should default to :text for :text column types' do
417
- default_input_type(:text).should == :text
418
- end
419
-
420
- it 'should default to :date_select for :date column types' do
421
- default_input_type(:date).should == :date_select
422
- end
423
-
424
- it 'should default to :datetime_select for :datetime and :timestamp column types' do
425
- default_input_type(:datetime).should == :datetime_select
426
- default_input_type(:timestamp).should == :datetime_select
427
- end
428
-
429
- it 'should default to :time_select for :time column types' do
430
- default_input_type(:time).should == :time_select
431
- end
432
-
433
- it 'should default to :boolean for :boolean column types' do
434
- default_input_type(:boolean).should == :boolean
435
- end
436
-
437
- it 'should default to :string for :string column types' do
438
- default_input_type(:string).should == :string
439
- end
440
-
441
- it 'should default to :number for :integer, :float and :decimal column types' do
442
- default_input_type(:integer).should == :number
443
- default_input_type(:float).should == :number
444
- default_input_type(:decimal).should == :number
445
- end
446
-
447
- it 'should default to :country for :string columns named country' do
448
- default_input_type(:string, :country).should == :country
449
- end
450
-
451
- it 'should default to :email for :string columns matching email' do
452
- default_input_type(:string, :email).should == :email
453
- default_input_type(:string, :customer_email).should == :email
454
- default_input_type(:string, :email_work).should == :email
455
- end
456
-
457
- it 'should default to :url for :string columns named url or website' do
458
- default_input_type(:string, :url).should == :url
459
- default_input_type(:string, :website).should == :url
460
- default_input_type(:string, :my_url).should == :url
461
- default_input_type(:string, :hurl).should_not == :url
462
- end
463
-
464
- it 'should default to :phone for :string columns named phone or fax' do
465
- default_input_type(:string, :phone).should == :phone
466
- default_input_type(:string, :fax).should == :phone
467
- end
468
-
469
- it 'should default to :search for :string columns named search' do
470
- default_input_type(:string, :search).should == :search
471
- end
472
-
473
- describe 'defaulting to file column' do
474
- Formtastic::FormBuilder.file_methods.each do |method|
475
- it "should default to :file for attributes that respond to ##{method}" do
476
- column = mock('column')
477
-
478
- Formtastic::FormBuilder.file_methods.each do |test|
479
- ### TODO: Check if this is ok
480
- column.stub!(method).with(test).and_return(method == test)
481
- end
482
-
483
- @new_post.should_receive(method).and_return(column)
484
-
485
- semantic_form_for(@new_post) do |builder|
486
- builder.send(:default_input_type, method).should == :file
487
- end
488
- end
489
- end
490
-
491
- end
492
- end
493
-
494
- it 'should call the corresponding input class with .to_html' do
495
- [:select, :time_zone, :radio, :date_select, :datetime_select, :time_select, :boolean, :check_boxes, :hidden, :string, :password, :number, :text, :file].each do |input_style|
496
- @new_post.stub!(:generic_column_name)
497
- @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
498
- semantic_form_for(@new_post) do |builder|
499
- input_instance = mock('Input instance')
500
- input_class = "#{input_style.to_s}_input".classify
501
- input_constant = "FormtasticBootstrap::Inputs::#{input_class}".constantize
502
-
503
- input_constant.should_receive(:new).and_return(input_instance)
504
- input_instance.should_receive(:to_html).and_return("some HTML")
505
-
506
- concat(builder.input(:generic_column_name, :as => input_style))
507
- end
508
- end
509
- end
510
-
511
- end
512
-
513
- describe ':label option' do
514
-
515
- describe 'when provided' do
516
- it 'should be passed down to the label tag' do
517
- concat(semantic_form_for(@new_post) do |builder|
518
- concat(builder.input(:title, :label => "Kustom"))
519
- end)
520
- output_buffer.should have_tag("form div label", /Kustom/)
521
- end
522
-
523
- it 'should not generate a label if false' do
524
- concat(semantic_form_for(@new_post) do |builder|
525
- concat(builder.input(:title, :label => false))
526
- end)
527
- output_buffer.should_not have_tag("form div label")
528
- end
529
-
530
- it 'should be dupped if frozen' do
531
- concat(semantic_form_for(@new_post) do |builder|
532
- concat(builder.input(:title, :label => "Kustom".freeze))
533
- end)
534
- output_buffer.should have_tag("form div label", /Kustom/)
535
- end
536
- end
537
-
538
- describe 'when not provided' do
539
- describe 'when localized label is provided' do
540
- describe 'and object is given' do
541
- describe 'and label_str_method not :humanize' do
542
- it 'should render a label with localized text and not apply the label_str_method' do
543
- with_config :label_str_method, :reverse do
544
- @localized_label_text = 'Localized title'
545
- @new_post.stub!(:meta_description)
546
- ::I18n.backend.store_translations :en,
547
- :formtastic => {
548
- :labels => {
549
- :meta_description => @localized_label_text
550
- }
551
- }
552
-
553
- concat(semantic_form_for(@new_post) do |builder|
554
- concat(builder.input(:meta_description))
555
- end)
556
- output_buffer.should have_tag('form div label', /Localized title/)
557
- end
558
- end
559
- end
560
- end
561
- end
562
-
563
- describe 'when localized label is NOT provided' do
564
- describe 'and object is not given' do
565
- it 'should default the humanized method name, passing it down to the label tag' do
566
- ::I18n.backend.store_translations :en, :formtastic => {}
567
- with_config :label_str_method, :humanize do
568
- concat(semantic_form_for(:project, :url => 'http://test.host') do |builder|
569
- concat(builder.input(:meta_description))
570
- end)
571
- output_buffer.should have_tag("form div label", /#{'meta_description'.humanize}/)
572
- end
573
- end
574
- end
575
-
576
- describe 'and object is given' do
577
- it 'should delegate the label logic to class human attribute name and pass it down to the label tag' do
578
- @new_post.stub!(:meta_description) # a two word method name
579
- @new_post.class.should_receive(:human_attribute_name).with('meta_description').and_return('meta_description'.humanize)
580
-
581
- concat(semantic_form_for(@new_post) do |builder|
582
- concat(builder.input(:meta_description))
583
- end)
584
- output_buffer.should have_tag("form div label", /#{'meta_description'.humanize}/)
585
- end
586
- end
587
-
588
- describe 'and object is given with label_str_method set to :capitalize' do
589
- it 'should capitalize method name, passing it down to the label tag' do
590
- with_config :label_str_method, :capitalize do
591
- @new_post.stub!(:meta_description)
592
-
593
- concat(semantic_form_for(@new_post) do |builder|
594
- concat(builder.input(:meta_description))
595
- end)
596
- output_buffer.should have_tag("form div label", /#{'meta_description'.capitalize}/)
597
- end
598
- end
599
- end
600
- end
601
-
602
- describe 'when localized label is provided' do
603
- before do
604
- @localized_label_text = 'Localized title'
605
- @default_localized_label_text = 'Default localized title'
606
- ::I18n.backend.store_translations :en,
607
- :formtastic => {
608
- :labels => {
609
- :title => @default_localized_label_text,
610
- :published => @default_localized_label_text,
611
- :post => {
612
- :title => @localized_label_text,
613
- :published => @default_localized_label_text
614
- }
615
- }
616
- }
617
- end
618
-
619
- it 'should render a label with localized label (I18n)' do
620
- with_config :i18n_lookups_by_default, false do
621
- concat(semantic_form_for(@new_post) do |builder|
622
- concat(builder.input(:title, :label => true))
623
- concat(builder.input(:published, :as => :boolean, :label => true))
624
- end)
625
- output_buffer.should have_tag('form div label', Regexp.new('^' + @localized_label_text))
626
- end
627
- end
628
-
629
- it 'should render a hint paragraph containing an optional localized label (I18n) if first is not set' do
630
- with_config :i18n_lookups_by_default, false do
631
- ::I18n.backend.store_translations :en,
632
- :formtastic => {
633
- :labels => {
634
- :post => {
635
- :title => nil,
636
- :published => nil
637
- }
638
- }
639
- }
640
- concat(semantic_form_for(@new_post) do |builder|
641
- concat(builder.input(:title, :label => true))
642
- concat(builder.input(:published, :as => :boolean, :label => true))
643
- end)
644
- output_buffer.should have_tag('form div label', Regexp.new('^' + @default_localized_label_text))
645
- end
646
- end
647
- end
648
- end
649
-
650
- end
651
-
652
- describe ':hint option' do
653
-
654
- describe 'when provided' do
655
-
656
- after do
657
- Formtastic::FormBuilder.default_hint_class = "inline-hints"
658
- end
659
-
660
- it 'should be passed down to the paragraph tag' do
661
- hint_text = "this is the title of the post"
662
- concat(semantic_form_for(@new_post) do |builder|
663
- concat(builder.input(:title, :hint => hint_text))
664
- end)
665
- output_buffer.should have_tag("form div p.inline-hints", hint_text)
666
- end
667
-
668
- it 'should have a custom hint class if I ask for one' do
669
- with_deprecation_silenced do
670
- hint_text = "this is the title of the post"
671
- concat(semantic_form_for(@new_post) do |builder|
672
- concat(builder.input(:title, :hint => hint_text, :hint_class => 'custom-hint-class'))
673
- end)
674
- output_buffer.should have_tag("form div p.custom-hint-class", hint_text)
675
- end
676
- end
677
-
678
- it 'should have a custom hint class defaulted for all forms' do
679
- hint_text = "this is the title of the post"
680
- Formtastic::FormBuilder.default_hint_class = "custom-hint-class"
681
- concat(semantic_form_for(@new_post) do |builder|
682
- concat(builder.input(:title, :hint => hint_text))
683
- end)
684
- output_buffer.should have_tag("form div p.custom-hint-class", hint_text)
685
- end
686
- end
687
-
688
- describe 'when not provided' do
689
- describe 'when localized hint (I18n) is provided' do
690
- before do
691
- @localized_hint_text = "This is the localized hint."
692
- @default_localized_hint_text = "This is the default localized hint."
693
- ::I18n.backend.store_translations :en,
694
- :formtastic => {
695
- :hints => {
696
- :title => @default_localized_hint_text,
697
- }
698
- }
699
- end
700
-
701
- after do
702
- ::I18n.backend.reload!
703
- end
704
-
705
- describe 'when provided value (hint value) is set to TRUE' do
706
- it 'should render a hint paragraph containing a localized hint (I18n)' do
707
- with_config :i18n_lookups_by_default, false do
708
- ::I18n.backend.store_translations :en,
709
- :formtastic => {
710
- :hints => {
711
- :post => {
712
- :title => @localized_hint_text
713
- }
714
- }
715
- }
716
- concat(semantic_form_for(@new_post) do |builder|
717
- concat(builder.input(:title, :hint => true))
718
- end)
719
- output_buffer.should have_tag('form div p.inline-hints', @localized_hint_text)
720
- end
721
- end
722
-
723
- it 'should render a hint paragraph containing a localized hint (I18n) with a custom hint class if i ask for one' do
724
- with_config :i18n_lookups_by_default, false do
725
- ::I18n.backend.store_translations :en,
726
- :formtastic => {
727
- :hints => {
728
- :post => {
729
- :title => @localized_hint_text
730
- }
731
- }
732
- }
733
- with_deprecation_silenced do
734
- concat(semantic_form_for(@new_post) do |builder|
735
- concat(builder.input(:title, :hint => true, :hint_class => 'custom-hint-class'))
736
- end)
737
- end
738
- output_buffer.should have_tag('form div p.custom-hint-class', @localized_hint_text)
739
- end
740
- end
741
-
742
- it 'should render a hint paragraph containing an optional localized hint (I18n) if first is not set' do
743
- with_config :i18n_lookups_by_default, false do
744
- concat(semantic_form_for(@new_post) do |builder|
745
- concat(builder.input(:title, :hint => true))
746
- end)
747
- output_buffer.should have_tag('form div p.inline-hints', @default_localized_hint_text)
748
- end
749
- end
750
- end
751
-
752
- describe 'when provided value (label value) is set to FALSE' do
753
- it 'should not render a hint paragraph' do
754
- with_config :i18n_lookups_by_default, false do
755
- concat(semantic_form_for(@new_post) do |builder|
756
- concat(builder.input(:title, :hint => false))
757
- end)
758
- output_buffer.should_not have_tag('form div p.inline-hints', @localized_hint_text)
759
- end
760
- end
761
- end
762
- end
763
-
764
- describe 'when localized hint (I18n) is a model with attribute hints' do
765
- it "should see the provided hash as a blank entry" do
766
- with_config :i18n_lookups_by_default, false do
767
- ::I18n.backend.store_translations :en,
768
- :formtastic => {
769
- :hints => {
770
- :title => { # movie title
771
- :summary => @localized_hint_text # summary of movie
772
- }
773
- }
774
- }
775
- semantic_form_for(@new_post) do |builder|
776
- concat(builder.input(:title, :hint => true))
777
- end
778
- output_buffer.should_not have_tag('form div p.inline-hints', @localized_hint_text)
779
- end
780
- end
781
- end
782
-
783
- describe 'when localized hint (I18n) is not provided' do
784
- it 'should not render a hint paragraph' do
785
- with_config :i18n_lookups_by_default, false do
786
- concat(semantic_form_for(@new_post) do |builder|
787
- concat(builder.input(:title))
788
- end)
789
- output_buffer.should_not have_tag('form div p.inline-hints')
790
- end
791
- end
792
- end
793
- end
794
-
795
- end
796
-
797
- describe ':wrapper_html option' do
798
-
799
- describe 'when provided' do
800
- it 'should be passed down to the div tag' do
801
- concat(semantic_form_for(@new_post) do |builder|
802
- concat(builder.input(:title, :wrapper_html => {:id => :another_id}))
803
- end)
804
- output_buffer.should have_tag("form div#another_id")
805
- end
806
-
807
- it 'should append given classes to div default classes' do
808
- concat(semantic_form_for(@new_post) do |builder|
809
- concat(builder.input(:title, :wrapper_html => {:class => :another_class}, :required => true))
810
- end)
811
- output_buffer.should have_tag("form div.string")
812
- output_buffer.should have_tag("form div.required")
813
- output_buffer.should have_tag("form div.another_class")
814
- end
815
-
816
- it 'should allow classes to be an array' do
817
- concat(semantic_form_for(@new_post) do |builder|
818
- concat(builder.input(:title, :wrapper_html => {:class => [ :my_class, :another_class ]}))
819
- end)
820
- output_buffer.should have_tag("form div.string")
821
- output_buffer.should have_tag("form div.my_class")
822
- output_buffer.should have_tag("form div.another_class")
823
- end
824
- end
825
-
826
- describe 'when not provided' do
827
- it 'should use default id and class' do
828
- concat(semantic_form_for(@new_post) do |builder|
829
- concat(builder.input(:title))
830
- end)
831
- output_buffer.should have_tag("form div#post_title_input")
832
- output_buffer.should have_tag("form div.string")
833
- end
834
- end
835
-
836
- end
837
-
838
- describe ':collection option' do
839
-
840
- it "should be required on polymorphic associations" do
841
- @new_post.stub!(:commentable)
842
- @new_post.class.stub!(:reflections).and_return({
843
- :commentable => mock('macro_reflection', :options => { :polymorphic => true }, :macro => :belongs_to)
844
- })
845
- @new_post.stub!(:column_for_attribute).with(:commentable).and_return(
846
- mock('column', :type => :integer)
847
- )
848
- @new_post.class.stub!(:reflect_on_association).with(:commentable).and_return(
849
- mock('reflection', :macro => :belongs_to, :options => { :polymorphic => true })
850
- )
851
- expect {
852
- concat(semantic_form_for(@new_post) do |builder|
853
- concat(builder.inputs do
854
- concat(builder.input :commentable)
855
- end)
856
- end)
857
- }.to raise_error(Formtastic::PolymorphicInputWithoutCollectionError)
858
- end
859
-
860
- end
861
-
862
- end
863
-
864
- describe 'options re-use' do
865
-
866
- it 'should retain :as option when re-using the same options hash' do
867
- my_options = { :as => :string }
868
- output = ''
869
-
870
- concat(semantic_form_for(@new_post) do |builder|
871
- concat(builder.input(:title, my_options))
872
- concat(builder.input(:publish_at, my_options))
873
- end)
874
- output_buffer.should have_tag 'div.string', :count => 2
875
- end
876
-
877
-
878
- end
879
-
880
- describe 'instantiating an input class' do
881
-
882
- context 'when a class does not exist' do
883
- it "should raise an error" do
884
- lambda {
885
- concat(semantic_form_for(@new_post) do |builder|
886
- builder.input(:title, :as => :non_existant)
887
- end)
888
- }.should raise_error(Formtastic::UnknownInputError)
889
- end
890
- end
891
-
892
- context 'when a customized top-level class does not exist' do
893
-
894
- it 'should instantiate the Formtastic input' do
895
- input = mock('input', :to_html => 'some HTML')
896
- Formtastic::Inputs::StringInput.should_receive(:new).and_return(input)
897
- concat(semantic_form_for(@new_post) do |builder|
898
- builder.input(:title, :as => :string)
899
- end)
900
- end
901
-
902
- end
903
-
904
- describe 'when a top-level input class exists' do
905
- it "should instantiate the top-level input instead of the Formtastic one" do
906
- class ::StringInput < Formtastic::Inputs::StringInput
907
- end
908
-
909
- input = mock('input', :to_html => 'some HTML')
910
- Formtastic::Inputs::StringInput.should_not_receive(:new).and_return(input)
911
- ::StringInput.should_receive(:new).and_return(input)
912
-
913
- concat(semantic_form_for(@new_post) do |builder|
914
- builder.input(:title, :as => :string)
915
- end)
916
- end
917
- end
918
-
919
- describe 'when instantiated multiple times with the same input type' do
920
-
921
- it "should be cached (not calling the internal methods)" do
922
- # TODO this is really tied to the underlying implementation
923
- concat(semantic_form_for(@new_post) do |builder|
924
- builder.should_receive(:custom_input_class_name).with(:string).once.and_return(::Formtastic::Inputs::StringInput)
925
- builder.input(:title, :as => :string)
926
- builder.input(:title, :as => :string)
927
- end)
928
- end
929
-
930
- end
931
-
932
- end
933
-
934
- end
935
-