bootstrap_form 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,53 +26,79 @@ module BootstrapForm
26
26
  end
27
27
 
28
28
  FIELD_HELPERS.each do |method_name|
29
- define_method(method_name) do |name, options = {}|
29
+ with_method_name = "#{method_name}_with_bootstrap"
30
+ without_method_name = "#{method_name}_without_bootstrap"
31
+
32
+ define_method(with_method_name) do |name, options = {}|
30
33
  form_group_builder(name, options) do
31
34
  prepend_and_append_input(options) do
32
- super(name, options)
35
+ send(without_method_name, name, options)
33
36
  end
34
37
  end
35
38
  end
39
+
40
+ alias_method_chain method_name, :bootstrap
36
41
  end
37
42
 
38
43
  DATE_SELECT_HELPERS.each do |method_name|
39
- define_method(method_name) do |name, options = {}, html_options = {}|
44
+ with_method_name = "#{method_name}_with_bootstrap"
45
+ without_method_name = "#{method_name}_without_bootstrap"
46
+
47
+ define_method(with_method_name) do |name, options = {}, html_options = {}|
40
48
  form_group_builder(name, options, html_options) do
41
- content_tag(:div, super(name, options, html_options), class: control_specific_class(method_name))
49
+ content_tag(:div, send(without_method_name, name, options, html_options), class: control_specific_class(method_name))
42
50
  end
43
51
  end
52
+
53
+ alias_method_chain method_name, :bootstrap
44
54
  end
45
55
 
46
- def file_field(name, options = {})
56
+ def file_field_with_bootstrap(name, options = {})
47
57
  form_group_builder(name, options.reverse_merge(control_class: nil)) do
48
- super(name, options)
58
+ file_field_without_bootstrap(name, options)
49
59
  end
50
60
  end
51
61
 
52
- def select(method, choices, options = {}, html_options = {})
62
+ alias_method_chain :file_field, :bootstrap
63
+
64
+ def select_with_bootstrap(method, choices, options = {}, html_options = {})
53
65
  form_group_builder(method, options, html_options) do
54
- super(method, choices, options, html_options)
66
+ select_without_bootstrap(method, choices, options, html_options)
55
67
  end
56
68
  end
57
69
 
58
- def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
70
+ alias_method_chain :select, :bootstrap
71
+
72
+ def collection_select_with_bootstrap(method, collection, value_method, text_method, options = {}, html_options = {})
59
73
  form_group_builder(method, options, html_options) do
60
- super(method, collection, value_method, text_method, options, html_options)
74
+ collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options)
61
75
  end
62
76
  end
63
77
 
64
- def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
78
+ alias_method_chain :collection_select, :bootstrap
79
+
80
+ def grouped_collection_select_with_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
65
81
  form_group_builder(method, options, html_options) do
66
- super(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
82
+ grouped_collection_select_without_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
67
83
  end
68
84
  end
69
85
 
70
- def check_box(name, options = {}, checked_value = "1", unchecked_value = "0", &block)
86
+ alias_method_chain :grouped_collection_select, :bootstrap
87
+
88
+ def time_zone_select_with_bootstrap(method, priority_zones = nil, options = {}, html_options = {})
89
+ form_group_builder(method, options, html_options) do
90
+ time_zone_select_without_bootstrap(method, priority_zones, options, html_options)
91
+ end
92
+ end
93
+
94
+ alias_method_chain :time_zone_select, :bootstrap
95
+
96
+ def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_value = "0", &block)
71
97
  options = options.symbolize_keys!
72
98
 
73
- html = super(name, options.except(:label, :help, :inline), checked_value, unchecked_value)
99
+ html = check_box_without_bootstrap(name, options.except(:label, :help, :inline), checked_value, unchecked_value)
74
100
  label_content = block_given? ? capture(&block) : options[:label]
75
- html.concat(" ").concat(label_content || object.class.human_attribute_name(name) || name.to_s.humanize)
101
+ html.concat(" ").concat(label_content || (object && object.class.human_attribute_name(name)) || name.to_s.humanize)
76
102
 
77
103
  label_name = name
78
104
  label_name = "#{name}_#{checked_value}" if options[:multiple]
@@ -86,22 +112,31 @@ module BootstrapForm
86
112
  end
87
113
  end
88
114
 
89
- def radio_button(name, value, *args)
115
+ alias_method_chain :check_box, :bootstrap
116
+
117
+ def radio_button_with_bootstrap(name, value, *args)
90
118
  options = args.extract_options!.symbolize_keys!
91
119
  args << options.except(:label, :help, :inline)
92
120
 
93
- html = super(name, value, *args) + " " + options[:label]
121
+ html = radio_button_without_bootstrap(name, value, *args) + " " + options[:label]
94
122
 
95
- css = "radio"
96
- css << "-inline" if options[:inline]
97
- label(name, html, class: css, for: nil)
123
+ if options[:inline]
124
+ label(name, html, class: "radio-inline", value: value)
125
+ else
126
+ content_tag(:div, class: "radio") do
127
+ label(name, html, value: value)
128
+ end
129
+ end
98
130
  end
99
131
 
132
+ alias_method_chain :radio_button, :bootstrap
133
+
100
134
  def collection_check_boxes(*args)
101
- inputs_collection(*args) do |name, value, options|
135
+ html = inputs_collection(*args) do |name, value, options|
102
136
  options[:multiple] = true
103
137
  check_box(name, options, value, nil)
104
138
  end
139
+ hidden_field(args.first,{value: "", multiple: true}).concat(html)
105
140
  end
106
141
 
107
142
  def collection_radio_buttons(*args)
@@ -122,29 +157,42 @@ module BootstrapForm
122
157
 
123
158
  def form_group(*args, &block)
124
159
  options = args.extract_options!
125
- name = args.first
126
-
160
+ name = args.first
161
+
127
162
  options[:class] = ["form-group", options[:class]].compact.join(' ')
128
163
  options[:class] << " #{error_class}" if has_error?(name)
164
+ options[:class] << " #{feedback_class}" if options[:icon]
165
+
166
+ content_tag(:div, options.except(:id, :label, :help, :icon, :label_col, :control_col, :layout)) do
167
+ label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
168
+ control = capture(&block).to_s
169
+ control.concat(generate_help(name, options[:help]).to_s)
170
+ control.concat(generate_icon(options[:icon])) if options[:icon]
129
171
 
130
- content_tag(:div, options.except(:id, :label, :help, :label_col, :control_col, :layout)) do
131
- label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout])
132
- control_and_help = capture(&block).concat(generate_help(name, options[:help]))
133
172
  if get_group_layout(options[:layout]) == :horizontal
134
- control_and_help = content_tag(:div, control_and_help, class: (options[:control_col] || control_col))
173
+ control_class = (options[:control_col] || control_col.clone)
174
+
175
+ unless options[:label]
176
+ control_offset = offset_col(/([0-9]+)$/.match(options[:label_col] || default_label_col))
177
+ control_class.concat(" #{control_offset}")
178
+ end
179
+ control = content_tag(:div, control, class: control_class)
135
180
  end
136
- concat(label).concat(control_and_help)
181
+
182
+ concat(label).concat(control)
137
183
  end
138
184
  end
139
185
 
140
- def fields_for(record_name, record_object = nil, fields_options = {}, &block)
186
+ def fields_for_with_bootstrap(record_name, record_object = nil, fields_options = {}, &block)
141
187
  fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
142
188
  fields_options[:layout] ||= options[:layout]
143
189
  fields_options[:label_col] = fields_options[:label_col].present? ? "#{fields_options[:label_col]} #{label_class}" : options[:label_col]
144
190
  fields_options[:control_col] ||= options[:control_col]
145
- super(record_name, record_object, fields_options, &block)
191
+ fields_for_without_bootstrap(record_name, record_object, fields_options, &block)
146
192
  end
147
193
 
194
+ alias_method_chain :fields_for, :bootstrap
195
+
148
196
  private
149
197
 
150
198
  def horizontal?
@@ -159,6 +207,10 @@ module BootstrapForm
159
207
  "col-sm-2"
160
208
  end
161
209
 
210
+ def offset_col(offset)
211
+ "col-sm-offset-#{offset}"
212
+ end
213
+
162
214
  def default_control_col
163
215
  "col-sm-10"
164
216
  end
@@ -179,6 +231,10 @@ module BootstrapForm
179
231
  "has-error"
180
232
  end
181
233
 
234
+ def feedback_class
235
+ "has-feedback"
236
+ end
237
+
182
238
  def control_specific_class(method)
183
239
  "rails-bootstrap-forms-#{method.gsub(/_/, "-")}"
184
240
  end
@@ -200,12 +256,32 @@ module BootstrapForm
200
256
 
201
257
  label = options.delete(:label)
202
258
  label_class = hide_class if options.delete(:hide_label)
259
+ wrapper_class = options.delete(:wrapper_class)
260
+ wrapper_options = options.delete(:wrapper)
203
261
  help = options.delete(:help)
262
+ icon = options.delete(:icon)
204
263
  label_col = options.delete(:label_col)
205
264
  control_col = options.delete(:control_col)
206
265
  layout = get_group_layout(options.delete(:layout))
266
+ form_group_options = {
267
+ id: options[:id],
268
+ label: {
269
+ text: label,
270
+ class: label_class
271
+ },
272
+ help: help,
273
+ icon: icon,
274
+ label_col: label_col,
275
+ control_col: control_col,
276
+ layout: layout,
277
+ class: wrapper_class
278
+ }
279
+
280
+ if wrapper_options.is_a?(Hash)
281
+ form_group_options.reverse_merge!(wrapper_options)
282
+ end
207
283
 
208
- form_group(method, id: options[:id], label: { text: label, class: label_class }, help: help, label_col: label_col, control_col: control_col, layout: layout) do
284
+ form_group(method, form_group_options) do
209
285
  yield
210
286
  end
211
287
  end
@@ -217,22 +293,24 @@ module BootstrapForm
217
293
  end
218
294
 
219
295
  def generate_label(id, name, options, custom_label_col, group_layout)
220
- if options
221
- options[:for] = id if acts_like_form_tag
222
- classes = [options[:class], label_class]
223
- classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal
224
- options[:class] = classes.compact.join(" ")
225
-
226
- label(name, options[:text], options.except(:text))
227
- elsif get_group_layout(group_layout) == :horizontal
228
- # no label. create an empty one to keep proper form alignment.
229
- content_tag(:label, "", class: "#{label_class} #{label_col}")
230
- end
296
+ options[:for] = id if acts_like_form_tag
297
+ classes = [options[:class], label_class]
298
+ classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal
299
+ options[:class] = classes.compact.join(" ")
300
+
301
+ label(name, options[:text], options.except(:text))
231
302
  end
232
303
 
233
304
  def generate_help(name, help_text)
234
305
  help_text = object.errors[name].join(", ") if has_error?(name) && inline_errors
235
- content_tag(:span, help_text, class: "help-block") if help_text
306
+ return if help_text === false
307
+
308
+ help_text ||= I18n.t(name, scope: "activerecord.help.#{object.class.to_s.downcase}", default: '')
309
+ content_tag(:span, help_text, class: 'help-block') if help_text.present?
310
+ end
311
+
312
+ def generate_icon(icon)
313
+ content_tag(:span, "", class: "glyphicon glyphicon-#{icon} form-control-feedback")
236
314
  end
237
315
 
238
316
  def inputs_collection(name, collection, value, text, options = {}, &block)
@@ -241,7 +319,13 @@ module BootstrapForm
241
319
 
242
320
  collection.each do |obj|
243
321
  input_options = options.merge(label: obj.send(text))
244
- input_options[:checked] = input_options[:checked] == obj.send(value) if input_options[:checked]
322
+
323
+ if checked = input_options[:checked]
324
+ input_options[:checked] = checked == obj.send(value) ||
325
+ checked.try(:include?, obj.send(value)) ||
326
+ checked == obj ||
327
+ checked.try(:include?, obj)
328
+ end
245
329
 
246
330
  input_options.delete(:class)
247
331
  inputs << block.call(name, obj.send(value), input_options)
@@ -7,6 +7,9 @@ module BootstrapForm
7
7
  def bootstrap_form_for(object, options = {}, &block)
8
8
  options.reverse_merge!({builder: BootstrapForm::FormBuilder})
9
9
 
10
+ options[:html] ||= {}
11
+ options[:html][:role] ||= 'form'
12
+
10
13
  layout = case options[:layout]
11
14
  when :inline
12
15
  "form-inline"
@@ -15,7 +18,6 @@ module BootstrapForm
15
18
  end
16
19
 
17
20
  if layout
18
- options[:html] ||= {}
19
21
  options[:html][:class] = [options[:html][:class], layout].compact.join(" ")
20
22
  end
21
23
 
@@ -17,7 +17,7 @@ module BootstrapForm
17
17
  if object.respond_to?(:errors) && object.errors.full_messages.any?
18
18
  content_tag :div, class: css do
19
19
  concat content_tag :p, title
20
- concat error_summary unless inline_errors || options[:error_summary] == false
20
+ concat error_summary unless options[:error_summary] == false
21
21
  end
22
22
  end
23
23
  end
@@ -30,15 +30,24 @@ module BootstrapForm
30
30
  end
31
31
  end
32
32
 
33
- def errors_on(name)
33
+ def errors_on(name, options = {})
34
34
  if has_error?(name)
35
+ hide_attribute_name = options[:hide_attribute_name] || false
36
+
35
37
  content_tag :div, class: "alert alert-danger" do
36
- object.errors.full_messages_for(name).join(", ")
38
+ if hide_attribute_name
39
+ object.errors[name].join(", ")
40
+ else
41
+ object.errors.full_messages_for(name).join(", ")
42
+ end
37
43
  end
38
44
  end
39
45
  end
40
46
 
41
- def static_control(name, options = {}, &block)
47
+ def static_control(*args, &block)
48
+ options = args.extract_options!
49
+ name = args.first
50
+
42
51
  html = if block_given?
43
52
  capture(&block)
44
53
  else
@@ -54,12 +63,20 @@ module BootstrapForm
54
63
  options = options.extract!(:prepend, :append)
55
64
  input = capture(&block)
56
65
 
57
- input = content_tag(:span, options[:prepend], class: 'input-group-addon') + input if options[:prepend]
58
- input << content_tag(:span, options[:append], class: 'input-group-addon') if options[:append]
59
- input = content_tag(:div, input, class: 'input-group') if options[:prepend] || options[:append]
66
+ input = content_tag(:span, options[:prepend], class: input_group_class(options[:prepend])) + input if options[:prepend]
67
+ input << content_tag(:span, options[:append], class: input_group_class(options[:append])) if options[:append]
68
+ input = content_tag(:div, input, class: "input-group") unless options.empty?
60
69
  input
61
70
  end
62
71
 
72
+ def input_group_class(add_on_content)
73
+ if add_on_content.match /btn/
74
+ 'input-group-btn'
75
+ else
76
+ 'input-group-addon'
77
+ end
78
+ end
79
+
63
80
  def static_class
64
81
  "form-control-static"
65
82
  end
@@ -1,3 +1,3 @@
1
1
  module BootstrapForm
2
- VERSION = "2.1.1"
2
+ VERSION = "2.2.0"
3
3
  end
@@ -0,0 +1,71 @@
1
+ require 'test_helper'
2
+
3
+ class BootstrapCheckboxTest < ActionView::TestCase
4
+ include BootstrapForm::Helper
5
+
6
+ def setup
7
+ setup_test_fixture
8
+ end
9
+
10
+ test "check_box is wrapped correctly" do
11
+ expected = %{<div class="checkbox"><label for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label></div>}
12
+ assert_equal expected, @builder.check_box(:terms, label: 'I agree to the terms')
13
+ end
14
+
15
+ test "check_box label allows html" do
16
+ expected = %{<div class="checkbox"><label for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the <a href="#">terms</a></label></div>}
17
+ assert_equal expected, @builder.check_box(:terms, label: %{I agree to the <a href="#">terms</a>}.html_safe)
18
+ end
19
+
20
+ test "check_box accepts a block to define the label" do
21
+ expected = %{<div class="checkbox"><label for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label></div>}
22
+ assert_equal expected, @builder.check_box(:terms) { "I agree to the terms" }
23
+ end
24
+
25
+ test "check_box responds to checked_value and unchecked_value arguments" do
26
+ expected = %{<div class="checkbox"><label for="user_terms"><input name="user[terms]" type="hidden" value="no" /><input id="user_terms" name="user[terms]" type="checkbox" value="yes" /> I agree to the terms</label></div>}
27
+ assert_equal expected, @builder.check_box(:terms, {label: 'I agree to the terms'}, 'yes', 'no')
28
+ end
29
+
30
+ test "inline checkboxes" do
31
+ expected = %{<label class="checkbox-inline" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label>}
32
+ assert_equal expected, @builder.check_box(:terms, label: 'I agree to the terms', inline: true)
33
+ end
34
+
35
+ test 'collection_check_boxes renders the form_group correctly' do
36
+ collection = [Address.new(id: 1, street: 'Foobar')]
37
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">This is a checkbox collection</label><div class="checkbox"><label for="user_misc_1"><input id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foobar</label></div><span class="help-block">With a help!</span></div>}
38
+
39
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, label: 'This is a checkbox collection', help: 'With a help!')
40
+ end
41
+
42
+ test 'collection_check_boxes renders multiple checkboxes correctly' do
43
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
44
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_1"><input id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label></div><div class="checkbox"><label for="user_misc_2"><input id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div></div>}
45
+
46
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street)
47
+ end
48
+
49
+ test 'collection_check_boxes renders inline checkboxes correctly' do
50
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
51
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><label class="checkbox-inline" for="user_misc_1"><input id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label><label class="checkbox-inline" for="user_misc_2"><input id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div>}
52
+
53
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, inline: true)
54
+ end
55
+
56
+ test 'collection_check_boxes renders with checked option correctly' do
57
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
58
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_1"><input checked="checked" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label></div><div class="checkbox"><label for="user_misc_2"><input id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div></div>}
59
+
60
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: 1)
61
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection.first)
62
+ end
63
+
64
+ test 'collection_check_boxes renders with multiple checked options correctly' do
65
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
66
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="control-label" for="user_misc">Misc</label><div class="checkbox"><label for="user_misc_1"><input checked="checked" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label></div><div class="checkbox"><label for="user_misc_2"><input checked="checked" id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div></div>}
67
+
68
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: [1, 2])
69
+ assert_equal expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection)
70
+ end
71
+ end
@@ -0,0 +1,152 @@
1
+ require 'test_helper'
2
+
3
+ class BootstrapFieldsTest < ActionView::TestCase
4
+ include BootstrapForm::Helper
5
+
6
+ def setup
7
+ setup_test_fixture
8
+ end
9
+
10
+ test "color fields are wrapped correctly" do
11
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="color" value="#000000" /></div>}
12
+ assert_equal expected, @builder.color_field(:misc)
13
+ end
14
+
15
+ test "date fields are wrapped correctly" do
16
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="date" /></div>}
17
+ assert_equal expected, @builder.date_field(:misc)
18
+ end
19
+
20
+ test "date time fields are wrapped correctly" do
21
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="datetime" /></div>}
22
+ assert_equal expected, @builder.datetime_field(:misc)
23
+ end
24
+
25
+ test "date time local fields are wrapped correctly" do
26
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="datetime-local" /></div>}
27
+ assert_equal expected, @builder.datetime_local_field(:misc)
28
+ end
29
+
30
+ test "email fields are wrapped correctly" do
31
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="email" /></div>}
32
+ assert_equal expected, @builder.email_field(:misc)
33
+ end
34
+
35
+ test "file fields are wrapped correctly" do
36
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input id="user_misc" name="user[misc]" type="file" /></div>}
37
+ assert_equal expected, @builder.file_field(:misc)
38
+ end
39
+
40
+ test "hidden fields are supported" do
41
+ expected = %{<input id="user_misc" name="user[misc]" type="hidden" />}
42
+ assert_equal expected, @builder.hidden_field(:misc)
43
+ end
44
+
45
+ test "month local fields are wrapped correctly" do
46
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="month" /></div>}
47
+ assert_equal expected, @builder.month_field(:misc)
48
+ end
49
+
50
+ test "number fields are wrapped correctly" do
51
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="number" /></div>}
52
+ assert_equal expected, @builder.number_field(:misc)
53
+ end
54
+
55
+ test "password fields are wrapped correctly" do
56
+ expected = %{<div class="form-group"><label class="control-label" for="user_password">Password</label><input class="form-control" id="user_password" name="user[password]" type="password" /><span class="help-block">A good password should be at least six characters long</span></div>}
57
+ assert_equal expected, @builder.password_field(:password)
58
+ end
59
+
60
+ test "phone/telephone fields are wrapped correctly" do
61
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="tel" /></div>}
62
+ assert_equal expected, @builder.phone_field(:misc)
63
+ assert_equal expected, @builder.telephone_field(:misc)
64
+ end
65
+
66
+ test "range fields are wrapped correctly" do
67
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="range" /></div>}
68
+ assert_equal expected, @builder.range_field(:misc)
69
+ end
70
+
71
+ test "search fields are wrapped correctly" do
72
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="search" /></div>}
73
+ assert_equal expected, @builder.search_field(:misc)
74
+ end
75
+
76
+ test "text areas are wrapped correctly" do
77
+ expected = %{<div class="form-group"><label class="control-label" for="user_comments">Comments</label><textarea class="form-control" id="user_comments" name="user[comments]">\nmy comment</textarea></div>}
78
+ assert_equal expected, @builder.text_area(:comments)
79
+ end
80
+
81
+ test "text fields are wrapped correctly" do
82
+ expected = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
83
+ assert_equal expected, @builder.text_field(:email)
84
+ end
85
+
86
+ test "time fields are wrapped correctly" do
87
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="time" /></div>}
88
+ assert_equal expected, @builder.time_field(:misc)
89
+ end
90
+
91
+ test "url fields are wrapped correctly" do
92
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="url" /></div>}
93
+ assert_equal expected, @builder.url_field(:misc)
94
+ end
95
+
96
+ test "week fields are wrapped correctly" do
97
+ expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="week" /></div>}
98
+ assert_equal expected, @builder.week_field(:misc)
99
+ end
100
+
101
+ test "bootstrap_form_for helper works for associations" do
102
+ @user.address = Address.new(street: '123 Main Street')
103
+
104
+ output = bootstrap_form_for(@user) do |f|
105
+ f.fields_for :address do |af|
106
+ af.text_field(:street)
107
+ end
108
+ end
109
+
110
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="control-label" for="user_address_attributes_street">Street</label><input class="form-control" id="user_address_attributes_street" name="user[address_attributes][street]" type="text" value="123 Main Street" /></div></form>}
111
+ assert_equal expected, output
112
+ end
113
+
114
+ test "bootstrap_form_for helper works for serialized hash attributes" do
115
+ @user.preferences = { favorite_color: "cerulean" }
116
+
117
+ output = bootstrap_form_for(@user) do |f|
118
+ f.fields_for :preferences do |builder|
119
+ builder.text_field :favorite_color, value: @user.preferences[:favorite_color]
120
+ end
121
+ end
122
+
123
+ expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="control-label" for="user_preferences_favorite_color">Favorite color</label><input class="form-control" id="user_preferences_favorite_color" name="user[preferences][favorite_color]" type="text" value="cerulean" /></div></form>}
124
+ assert_equal expected, output
125
+ end
126
+
127
+ test "fields_for correctly passes horizontal style from parent builder" do
128
+ @user.address = Address.new(street: '123 Main Street')
129
+
130
+ output = bootstrap_form_for(@user, layout: :horizontal, label_col: 'col-sm-2', control_col: 'col-sm-10') do |f|
131
+ f.fields_for :address do |af|
132
+ af.text_field(:street)
133
+ end
134
+ end
135
+
136
+ expected = %{<form accept-charset="UTF-8" action="/users" class="form-horizontal" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="control-label col-sm-2" for="user_address_attributes_street">Street</label><div class="col-sm-10"><input class="form-control" id="user_address_attributes_street" name="user[address_attributes][street]" type="text" value="123 Main Street" /></div></div></form>}
137
+ assert_equal expected, output
138
+ end
139
+
140
+ test "fields_for correctly passes inline style from parent builder" do
141
+ @user.address = Address.new(street: '123 Main Street')
142
+
143
+ output = bootstrap_form_for(@user, layout: :inline) do |f|
144
+ f.fields_for :address do |af|
145
+ af.text_field(:street)
146
+ end
147
+ end
148
+
149
+ expected = %{<form accept-charset="UTF-8" action="/users" class="form-inline" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="control-label" for="user_address_attributes_street">Street</label><input class="form-control" id="user_address_attributes_street" name="user[address_attributes][street]" type="text" value="123 Main Street" /></div></form>}
150
+ assert_equal expected, output
151
+ end
152
+ end