comfy_bootstrap_form 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +621 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/stylesheets/rails_bootstrap_forms.css +10 -0
  6. data/lib/bootstrap_form.rb +13 -0
  7. data/lib/bootstrap_form/aliasing.rb +35 -0
  8. data/lib/bootstrap_form/form_builder.rb +460 -0
  9. data/lib/bootstrap_form/helper.rb +36 -0
  10. data/lib/bootstrap_form/helpers/bootstrap.rb +94 -0
  11. data/lib/bootstrap_form/helpers/nested_form.rb +33 -0
  12. data/lib/bootstrap_form/version.rb +3 -0
  13. data/lib/comfy_bootstrap_form.rb +1 -0
  14. data/test/bootstrap_checkbox_test.rb +144 -0
  15. data/test/bootstrap_fields_test.rb +152 -0
  16. data/test/bootstrap_form_group_test.rb +313 -0
  17. data/test/bootstrap_form_test.rb +276 -0
  18. data/test/bootstrap_other_components_test.rb +86 -0
  19. data/test/bootstrap_radio_button_test.rb +124 -0
  20. data/test/bootstrap_selects_test.rb +160 -0
  21. data/test/dummy/Gemfile +45 -0
  22. data/test/dummy/Gemfile.lock +120 -0
  23. data/test/dummy/README.rdoc +28 -0
  24. data/test/dummy/Rakefile +10 -0
  25. data/test/dummy/app/assets/javascripts/application.js +16 -0
  26. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  27. data/test/dummy/app/controllers/application_controller.rb +5 -0
  28. data/test/dummy/app/helpers/application_helper.rb +2 -0
  29. data/test/dummy/app/models/address.rb +3 -0
  30. data/test/dummy/app/models/faux_user.rb +9 -0
  31. data/test/dummy/app/models/super_user.rb +2 -0
  32. data/test/dummy/app/models/user.rb +9 -0
  33. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  34. data/test/dummy/bin/bundle +3 -0
  35. data/test/dummy/bin/rails +4 -0
  36. data/test/dummy/bin/rake +4 -0
  37. data/test/dummy/config.ru +4 -0
  38. data/test/dummy/config/application.rb +23 -0
  39. data/test/dummy/config/boot.rb +4 -0
  40. data/test/dummy/config/database.yml +25 -0
  41. data/test/dummy/config/environment.rb +5 -0
  42. data/test/dummy/config/environments/development.rb +29 -0
  43. data/test/dummy/config/environments/production.rb +80 -0
  44. data/test/dummy/config/environments/test.rb +53 -0
  45. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  46. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  47. data/test/dummy/config/initializers/generic_migration.rb +6 -0
  48. data/test/dummy/config/initializers/inflections.rb +16 -0
  49. data/test/dummy/config/initializers/mime_types.rb +5 -0
  50. data/test/dummy/config/initializers/secret_token.rb +12 -0
  51. data/test/dummy/config/initializers/session_store.rb +3 -0
  52. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  53. data/test/dummy/config/locales/en.yml +23 -0
  54. data/test/dummy/config/routes.rb +3 -0
  55. data/test/dummy/db/migrate/20130703191909_create_users.rb +13 -0
  56. data/test/dummy/db/migrate/20130703191937_create_addresses.rb +13 -0
  57. data/test/dummy/db/migrate/20130912171202_add_preferences_to_user.rb +5 -0
  58. data/test/dummy/db/migrate/20140327190145_add_terms_to_user.rb +5 -0
  59. data/test/dummy/db/migrate/20140922133133_add_type_to_users.rb +5 -0
  60. data/test/dummy/db/schema.rb +38 -0
  61. data/test/dummy/db/seeds.rb +7 -0
  62. data/test/dummy/db/test.sqlite3 +0 -0
  63. data/test/dummy/log/test.log +18394 -0
  64. data/test/dummy/public/404.html +58 -0
  65. data/test/dummy/public/422.html +58 -0
  66. data/test/dummy/public/500.html +57 -0
  67. data/test/dummy/public/favicon.ico +0 -0
  68. data/test/dummy/public/robots.txt +5 -0
  69. data/test/dummy/test/fixtures/addresses.yml +15 -0
  70. data/test/dummy/test/fixtures/users.yml +15 -0
  71. data/test/dummy/test/models/address_test.rb +7 -0
  72. data/test/dummy/test/models/user_test.rb +7 -0
  73. data/test/dummy/test/test_helper.rb +15 -0
  74. data/test/special_form_class_models_test.rb +43 -0
  75. data/test/test_helper.rb +86 -0
  76. metadata +309 -0
@@ -0,0 +1,36 @@
1
+ require_relative 'helpers/nested_form'
2
+
3
+ module BootstrapForm
4
+ module Helper
5
+ include ::BootstrapForm::Helpers::NestedForm
6
+
7
+ def bootstrap_form_for(object, options = {}, &block)
8
+ options.reverse_merge!({builder: BootstrapForm::FormBuilder})
9
+
10
+ options[:html] ||= {}
11
+ options[:html][:role] ||= 'form'
12
+
13
+ if options[:layout] == :inline
14
+ options[:html][:class] = [options[:html][:class], "form-inline"].compact.join(" ")
15
+ end
16
+
17
+ temporarily_disable_field_error_proc do
18
+ form_for(object, options, &block)
19
+ end
20
+ end
21
+
22
+ def bootstrap_form_tag(options = {}, &block)
23
+ options[:acts_like_form_tag] = true
24
+
25
+ bootstrap_form_for("", options, &block)
26
+ end
27
+
28
+ def temporarily_disable_field_error_proc
29
+ original_proc = ActionView::Base.field_error_proc
30
+ ActionView::Base.field_error_proc = proc { |input, instance| input }
31
+ yield
32
+ ensure
33
+ ActionView::Base.field_error_proc = original_proc
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,94 @@
1
+ module BootstrapForm
2
+ module Helpers
3
+ module Bootstrap
4
+ def submit(name = nil, options = {})
5
+ options.reverse_merge! class: 'btn btn-secondary'
6
+ super(name, options)
7
+ end
8
+
9
+ def primary(name = nil, options = {})
10
+ options.reverse_merge! class: 'btn btn-primary'
11
+ submit(name, options)
12
+ end
13
+
14
+ def alert_message(title, options = {})
15
+ css = options[:class] || 'alert alert-danger'
16
+
17
+ if object.respond_to?(:errors) && object.errors.full_messages.any?
18
+ content_tag :div, class: css do
19
+ concat content_tag :p, title
20
+ concat error_summary unless options[:error_summary] == false
21
+ end
22
+ end
23
+ end
24
+
25
+ def error_summary
26
+ content_tag :ul, class: 'rails-bootstrap-forms-error-summary' do
27
+ object.errors.full_messages.each do |error|
28
+ concat content_tag(:li, error)
29
+ end
30
+ end
31
+ end
32
+
33
+ def errors_on(name, options = {})
34
+ if has_error?(name)
35
+ hide_attribute_name = options[:hide_attribute_name] || false
36
+
37
+ content_tag :div, class: "alert alert-danger" do
38
+ if hide_attribute_name
39
+ object.errors[name].join(", ")
40
+ else
41
+ object.errors.full_messages_for(name).join(", ")
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def static_control(*args, &block)
48
+ options = args.extract_options!
49
+ name = args.first
50
+
51
+ html = if block_given?
52
+ capture(&block)
53
+ else
54
+ object.send(name)
55
+ end
56
+
57
+ form_group_builder(name, options) do
58
+ content_tag(:p, html, class: static_class)
59
+ end
60
+ end
61
+
62
+ def custom_control(*args, &block)
63
+ options = args.extract_options!
64
+ name = args.first
65
+
66
+ form_group_builder(name, options, &block)
67
+ end
68
+
69
+ def prepend_and_append_input(options, &block)
70
+ options = options.extract!(:prepend, :append, :input_group_class)
71
+ input_group_class = ["input-group", options[:input_group_class]].compact.join(' ')
72
+
73
+ input = capture(&block)
74
+
75
+ input = content_tag(:span, options[:prepend], class: input_group_class(options[:prepend])) + input if options[:prepend]
76
+ input << content_tag(:span, options[:append], class: input_group_class(options[:append])) if options[:append]
77
+ input = content_tag(:div, input, class: input_group_class) unless options.empty?
78
+ input
79
+ end
80
+
81
+ def input_group_class(add_on_content)
82
+ if add_on_content.match(/btn/)
83
+ 'input-group-btn'
84
+ else
85
+ 'input-group-addon'
86
+ end
87
+ end
88
+
89
+ def static_class
90
+ "form-control-static"
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,33 @@
1
+ begin
2
+ require 'nested_form/builder_mixin'
3
+
4
+ module BootstrapForm
5
+ class NestedFormBuilder < ::BootstrapForm::FormBuilder
6
+ include ::NestedForm::BuilderMixin
7
+ end
8
+ end
9
+
10
+ module BootstrapForm
11
+ module Helpers
12
+ module NestedForm
13
+ def bootstrap_nested_form_for(object, options = {}, &block)
14
+ options.reverse_merge!({builder: BootstrapForm::NestedFormBuilder})
15
+ bootstrap_form_for(object, options) do |f|
16
+ capture(f, &block).to_s << after_nested_form_callbacks
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ rescue LoadError
24
+ module BootstrapForm
25
+ module Helpers
26
+ module NestedForm
27
+ def bootstrap_nested_form_for(object, options = {}, &block)
28
+ raise 'nested_forms was not found. Is it in your Gemfile?'
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module BootstrapForm
2
+ VERSION = "4.0.0.beta1".freeze
3
+ end
@@ -0,0 +1 @@
1
+ require_relative "./bootstrap_form"
@@ -0,0 +1,144 @@
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="form-check"><label class="form-check-label" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label></div>}
12
+ assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms')
13
+ end
14
+
15
+ test "disabled check_box has proper wrapper classes" do
16
+ expected = %{<div class="form-check disabled"><label class="form-check-label" for="user_terms"><input disabled="disabled" name="user[terms]" type="hidden" value="0" /><input class="form-check-input" disabled="disabled" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label></div>}
17
+ assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms', disabled: true)
18
+ end
19
+
20
+ test "check_box label allows html" do
21
+ expected = %{<div class="form-check"><label class="form-check-label" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the <a href="#">terms</a></label></div>}
22
+ assert_equivalent_xml expected, @builder.check_box(:terms, label: %{I agree to the <a href="#">terms</a>}.html_safe)
23
+ end
24
+
25
+ test "check_box accepts a block to define the label" do
26
+ expected = %{<div class="form-check"><label class="form-check-label" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label></div>}
27
+ assert_equivalent_xml expected, @builder.check_box(:terms) { "I agree to the terms" }
28
+ end
29
+
30
+ test "check_box accepts a custom label class" do
31
+ expected = %{<div class="form-check"><label class="form-check-label btn" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1" /> Terms</label></div>}
32
+ assert_equivalent_xml expected, @builder.check_box(:terms, label_class: 'btn')
33
+ end
34
+
35
+ test "check_box responds to checked_value and unchecked_value arguments" do
36
+ expected = %{<div class="form-check"><label class="form-check-label" for="user_terms"><input name="user[terms]" type="hidden" value="no" /><input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="yes" /> I agree to the terms</label></div>}
37
+ assert_equivalent_xml expected, @builder.check_box(:terms, {label: 'I agree to the terms'}, 'yes', 'no')
38
+ end
39
+
40
+ test "inline checkboxes" do
41
+ expected = %{<label class="form-check-inline" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label>}
42
+ assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms', inline: true)
43
+ end
44
+
45
+ test "disabled inline check_box" do
46
+ expected = %{<label class="form-check-inline disabled" for="user_terms"><input disabled="disabled" name="user[terms]" type="hidden" value="0" /><input class="form-check-input" disabled="disabled" id="user_terms" name="user[terms]" type="checkbox" value="1" /> I agree to the terms</label>}
47
+ assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms', inline: true, disabled: true)
48
+ end
49
+
50
+ test "inline checkboxes with custom label class" do
51
+ expected = %{<label class="form-check-inline btn" for="user_terms"><input name="user[terms]" type="hidden" value="0" /><input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1" /> Terms</label>}
52
+ assert_equivalent_xml expected, @builder.check_box(:terms, inline: true, label_class: 'btn')
53
+ end
54
+
55
+ test 'collection_check_boxes renders the form_group correctly' do
56
+ collection = [Address.new(id: 1, street: 'Foobar')]
57
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">This is a checkbox collection</label><div class="form-check"><label class="form-check-label" for="user_misc_1"><input class="form-check-input" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foobar</label></div><span class="form-text text-muted">With a help!</span></div>}
58
+
59
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, label: 'This is a checkbox collection', help: 'With a help!')
60
+ end
61
+
62
+ test 'collection_check_boxes renders multiple checkboxes correctly' do
63
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
64
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_1"><input class="form-check-input" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label></div><div class="form-check"><label class="form-check-label" for="user_misc_2"><input class="form-check-input" id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div></div>}
65
+
66
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street)
67
+ end
68
+
69
+ test 'collection_check_boxes renders inline checkboxes correctly' do
70
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
71
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><label class="form-check-inline" for="user_misc_1"><input class="form-check-input" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label><label class="form-check-inline" for="user_misc_2"><input class="form-check-input" id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div>}
72
+
73
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, inline: true)
74
+ end
75
+
76
+ test 'collection_check_boxes renders with checked option correctly' do
77
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
78
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_1"><input checked="checked" class="form-check-input" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label></div><div class="form-check"><label class="form-check-label" for="user_misc_2"><input class="form-check-input" id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div></div>}
79
+
80
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: 1)
81
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection.first)
82
+ end
83
+
84
+ test 'collection_check_boxes renders with multiple checked options correctly' do
85
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
86
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_1"><input checked="checked" class="form-check-input" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> Foo</label></div><div class="form-check"><label class="form-check-label" for="user_misc_2"><input checked="checked" class="form-check-input" id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> Bar</label></div></div>}
87
+
88
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: [1, 2])
89
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection)
90
+ end
91
+
92
+ test 'collection_check_boxes sanitizes values when generating label `for`' do
93
+ collection = [Address.new(id: 1, street: 'Foo St')]
94
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_foo_st"><input class="form-check-input" id="user_misc_foo_st" name="user[misc][]" type="checkbox" value="Foo St" /> Foo St</label></div></div>}
95
+
96
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :street, :street)
97
+ end
98
+
99
+ test 'collection_check_boxes renders multiple checkboxes with labels defined by Proc :text_method correctly' do
100
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
101
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_1"><input class="form-check-input" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> ooF</label></div><div class="form-check"><label class="form-check-label" for="user_misc_2"><input class="form-check-input" id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> raB</label></div></div>}
102
+
103
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, Proc.new { |a| a.street.reverse })
104
+ end
105
+
106
+ test 'collection_check_boxes renders multiple checkboxes with values defined by Proc :value_method correctly' do
107
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
108
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_address_1"><input class="form-check-input" id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="form-check"><label class="form-check-label" for="user_misc_address_2"><input class="form-check-input" id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
109
+
110
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street)
111
+ end
112
+
113
+ test 'collection_check_boxes renders multiple checkboxes with labels defined by lambda :text_method correctly' do
114
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
115
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_1"><input class="form-check-input" id="user_misc_1" name="user[misc][]" type="checkbox" value="1" /> ooF</label></div><div class="form-check"><label class="form-check-label" for="user_misc_2"><input class="form-check-input" id="user_misc_2" name="user[misc][]" type="checkbox" value="2" /> raB</label></div></div>}
116
+
117
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, lambda { |a| a.street.reverse })
118
+ end
119
+
120
+ test 'collection_check_boxes renders multiple checkboxes with values defined by lambda :value_method correctly' do
121
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
122
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_address_1"><input class="form-check-input" id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="form-check"><label class="form-check-label" for="user_misc_address_2"><input class="form-check-input" id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
123
+
124
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street)
125
+ end
126
+
127
+ test 'collection_check_boxes renders with checked option correctly with Proc :value_method' do
128
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
129
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_address_1"><input checked="checked" class="form-check-input" id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="form-check"><label class="form-check-label" for="user_misc_address_2"><input class="form-check-input" id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
130
+
131
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, checked: "address_1")
132
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, checked: collection.first)
133
+ end
134
+
135
+ test 'collection_check_boxes renders with multiple checked options correctly with lambda :value_method' do
136
+ collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')]
137
+ expected = %{<input id="user_misc" multiple="multiple" name="user[misc][]" type="hidden" value="" /><div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><div class="form-check"><label class="form-check-label" for="user_misc_address_1"><input checked="checked" class="form-check-input" id="user_misc_address_1" name="user[misc][]" type="checkbox" value="address_1" /> Foo</label></div><div class="form-check"><label class="form-check-label" for="user_misc_address_2"><input checked="checked" class="form-check-input" id="user_misc_address_2" name="user[misc][]" type="checkbox" value="address_2" /> Bar</label></div></div>}
138
+
139
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, checked: ["address_1", "address_2"])
140
+ assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, checked: collection)
141
+ end
142
+
143
+
144
+ 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="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="color" value="#000000" /></div>}
12
+ assert_equivalent_xml expected, @builder.color_field(:misc)
13
+ end
14
+
15
+ test "date fields are wrapped correctly" do
16
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="date" /></div>}
17
+ assert_equivalent_xml 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="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="datetime" /></div>}
22
+ assert_equivalent_xml 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="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="datetime-local" /></div>}
27
+ assert_equivalent_xml 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="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="email" /></div>}
32
+ assert_equivalent_xml expected, @builder.email_field(:misc)
33
+ end
34
+
35
+ test "file fields are wrapped correctly" do
36
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input id="user_misc" name="user[misc]" type="file" /></div>}
37
+ assert_equivalent_xml 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_equivalent_xml 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="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="month" /></div>}
47
+ assert_equivalent_xml expected, @builder.month_field(:misc)
48
+ end
49
+
50
+ test "number fields are wrapped correctly" do
51
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="number" /></div>}
52
+ assert_equivalent_xml expected, @builder.number_field(:misc)
53
+ end
54
+
55
+ test "password fields are wrapped correctly" do
56
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_password">Password</label><input class="form-control" id="user_password" name="user[password]" type="password" /><span class="form-text text-muted">A good password should be at least six characters long</span></div>}
57
+ assert_equivalent_xml 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="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="tel" /></div>}
62
+ assert_equivalent_xml expected, @builder.phone_field(:misc)
63
+ assert_equivalent_xml expected, @builder.telephone_field(:misc)
64
+ end
65
+
66
+ test "range fields are wrapped correctly" do
67
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="range" /></div>}
68
+ assert_equivalent_xml expected, @builder.range_field(:misc)
69
+ end
70
+
71
+ test "search fields are wrapped correctly" do
72
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="search" /></div>}
73
+ assert_equivalent_xml expected, @builder.search_field(:misc)
74
+ end
75
+
76
+ test "text areas are wrapped correctly" do
77
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_comments">Comments</label><textarea class="form-control" id="user_comments" name="user[comments]">\nmy comment</textarea></div>}
78
+ assert_equivalent_xml expected, @builder.text_area(:comments)
79
+ end
80
+
81
+ test "text fields are wrapped correctly" do
82
+ expected = %{<div class="form-group"><label class="form-control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
83
+ assert_equivalent_xml expected, @builder.text_field(:email)
84
+ end
85
+
86
+ test "time fields are wrapped correctly" do
87
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="time" /></div>}
88
+ assert_equivalent_xml expected, @builder.time_field(:misc)
89
+ end
90
+
91
+ test "url fields are wrapped correctly" do
92
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="url" /></div>}
93
+ assert_equivalent_xml expected, @builder.url_field(:misc)
94
+ end
95
+
96
+ test "week fields are wrapped correctly" do
97
+ expected = %{<div class="form-group"><label class="form-control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="week" /></div>}
98
+ assert_equivalent_xml 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="form-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_equivalent_xml 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="form-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_equivalent_xml 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="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 row"><label class="form-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_equivalent_xml 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="form-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_equivalent_xml expected, output
151
+ end
152
+ end