diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index adf41e8f..00000000 --- a/.yarnrc +++ /dev/null @@ -1,5 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -lastUpdateCheck 1763256402231 diff --git a/README.md b/README.md index b233c2d3..b786e982 100644 --- a/README.md +++ b/README.md @@ -1490,38 +1490,38 @@ Generated HTML:
- -
is invalid
+ +
is invalid
- +
- + -
is invalid
+
is invalid
- +
- + -
is invalid
+
is invalid
- -
is invalid
+ +
is invalid
``` @@ -1551,8 +1551,8 @@ Generated HTML: ```html
- - + +
``` @@ -1649,7 +1649,7 @@ Which outputs: ```html
-
Email is invalid
+
Email is invalid
``` @@ -1670,7 +1670,7 @@ Which outputs: ```html
-
is invalid
+
is invalid
``` @@ -1689,7 +1689,7 @@ Which outputs: ```html
-
Email is invalid
+
Email is invalid
``` diff --git a/lib/bootstrap_form/components/labels.rb b/lib/bootstrap_form/components/labels.rb index 579957ed..e1e5c801 100644 --- a/lib/bootstrap_form/components/labels.rb +++ b/lib/bootstrap_form/components/labels.rb @@ -18,6 +18,7 @@ def generate_label(id, name, options, custom_label_col, group_layout) options[:class] = label_classes(name, options, custom_label_col, group_layout) options.delete(:class) if options[:class].none? + options[:id] = id.present? ? "#{id}_feedback" : field_id(name, :feedback) if error?(name) && label_errors label(name, label_text(name, options), options.except(:text)) end diff --git a/lib/bootstrap_form/components/validation.rb b/lib/bootstrap_form/components/validation.rb index affba190..8b4ba29d 100644 --- a/lib/bootstrap_form/components/validation.rb +++ b/lib/bootstrap_form/components/validation.rb @@ -61,14 +61,15 @@ def inline_error?(name) error?(name) && inline_errors end - def generate_error(name) + def generate_error(name, id) return unless inline_error?(name) help_text = get_error_messages(name) help_klass = "invalid-feedback" help_tag = :div + id = id.present? ? "#{id}_feedback" : field_id(name, :feedback) - content_tag(help_tag, help_text, class: help_klass) + content_tag(help_tag, help_text, class: help_klass, id:) end def get_error_messages(name) diff --git a/lib/bootstrap_form/form_group.rb b/lib/bootstrap_form/form_group.rb index c244f4b2..aeda4a76 100644 --- a/lib/bootstrap_form/form_group.rb +++ b/lib/bootstrap_form/form_group.rb @@ -23,7 +23,7 @@ def form_group_content_tag(name, field_name, without_field_name, options, html_o html_class = control_specific_class(field_name) html_class = "#{html_class} col-auto g-3" if @layout == :horizontal && options[:skip_inline].blank? tag.div(class: html_class) do - input_with_error(name) do + input_with_error(name, options[:id]) do send(without_field_name, name, options, html_options) end end diff --git a/lib/bootstrap_form/form_group_builder.rb b/lib/bootstrap_form/form_group_builder.rb index 79eff7e5..488a5d87 100644 --- a/lib/bootstrap_form/form_group_builder.rb +++ b/lib/bootstrap_form/form_group_builder.rb @@ -92,7 +92,11 @@ def form_group_css_options(method, html_options, options) # Add control_class; allow it to be overridden by :control_class option control_classes = css_options.delete(:control_class) { control_class } css_options[:class] = safe_join([control_classes, css_options[:class]].compact, " ") - css_options[:class] << " is-invalid" if error?(method) + if error?(method) + css_options[:class] << " is-invalid" + labelledby = options[:id].present? ? "#{options[:id]}_feedback" : field_id(method, :feedback) + css_options[:aria] = { labelledby: } + end css_options[:placeholder] = form_group_placeholder(options, method) if options[:label_as_placeholder] css_options end diff --git a/lib/bootstrap_form/helpers/bootstrap.rb b/lib/bootstrap_form/helpers/bootstrap.rb index 2048c448..0f1422b8 100644 --- a/lib/bootstrap_form/helpers/bootstrap.rb +++ b/lib/bootstrap_form/helpers/bootstrap.rb @@ -34,7 +34,7 @@ def errors_on(name, options={}) hide_attribute_name = options[:hide_attribute_name] || false custom_class = options[:custom_class] || false - tag.div class: custom_class || "invalid-feedback" do + tag.div(class: custom_class || "invalid-feedback", id: field_id(name, :feedback)) do errors = if hide_attribute_name object.errors[name] else @@ -66,20 +66,21 @@ def custom_control(*args, &) end def prepend_and_append_input(name, options, &) + id = options[:id] options = options.extract!(:prepend, :append, :input_group_class).compact input = capture(&) || ActiveSupport::SafeBuffer.new input = attach_input(options, :prepend) + input + attach_input(options, :append) - input << generate_error(name) + input << generate_error(name, id) options.present? && input = tag.div(input, class: ["input-group", options[:input_group_class]].compact) input end - def input_with_error(name, &) + def input_with_error(name, id, &) input = capture(&) - input << generate_error(name) + input << generate_error(name, id) end def input_group_content(content) diff --git a/lib/bootstrap_form/inputs/base.rb b/lib/bootstrap_form/inputs/base.rb index 94833bd9..807dccfa 100644 --- a/lib/bootstrap_form/inputs/base.rb +++ b/lib/bootstrap_form/inputs/base.rb @@ -24,6 +24,7 @@ def bootstrap_field(field_name) def bootstrap_select_group(field_name) define_method(:"#{field_name}_with_bootstrap") do |name, options={}, html_options={}| + options.delete(:id) html_options = html_options.reverse_merge(control_class: "form-select") form_group_builder(name, options, html_options) do form_group_content_tag(name, field_name, "#{field_name}_without_bootstrap", options, html_options) diff --git a/lib/bootstrap_form/inputs/check_box.rb b/lib/bootstrap_form/inputs/check_box.rb index fca776d0..866a9aa6 100644 --- a/lib/bootstrap_form/inputs/check_box.rb +++ b/lib/bootstrap_form/inputs/check_box.rb @@ -13,7 +13,7 @@ def check_box_with_bootstrap(name, options={}, checked_value="1", unchecked_valu content = tag.div(class: check_box_wrapper_class(options), **options[:wrapper].to_h.except(:class)) do html = check_box_without_bootstrap(name, check_box_options(name, options), checked_value, unchecked_value) html << check_box_label(name, options, checked_value, &block) unless options[:skip_label] - html << generate_error(name) if options[:error_message] + html << generate_error(name, options[:id]) if options[:error_message] html end wrapper(content, options) @@ -41,6 +41,10 @@ def check_box_options(name, options) :inline, :label, :label_class, :label_col, :layout, :skip_label, :switch, :wrapper, :wrapper_class) check_box_options[:class] = check_box_classes(name, options) + if error?(name) + labelledby = options[:id].present? ? "#{options[:id]}_feedback" : field_id(name, :feedback) + check_box_options[:aria] = { labelledby: } + end check_box_options.merge!(required_field_options(options, name)) end diff --git a/lib/bootstrap_form/inputs/collection_check_boxes.rb b/lib/bootstrap_form/inputs/collection_check_boxes.rb index 6b18edb7..4c028427 100644 --- a/lib/bootstrap_form/inputs/collection_check_boxes.rb +++ b/lib/bootstrap_form/inputs/collection_check_boxes.rb @@ -9,6 +9,7 @@ module CollectionCheckBoxes included do def collection_check_boxes_with_bootstrap(*args) + args[4]&.delete(:id) html = inputs_collection(*args) do |name, value, options| options[:multiple] = true check_box(name, options, value, nil) diff --git a/lib/bootstrap_form/inputs/collection_radio_buttons.rb b/lib/bootstrap_form/inputs/collection_radio_buttons.rb index be07db35..d6d6d5c5 100644 --- a/lib/bootstrap_form/inputs/collection_radio_buttons.rb +++ b/lib/bootstrap_form/inputs/collection_radio_buttons.rb @@ -9,6 +9,7 @@ module CollectionRadioButtons included do def collection_radio_buttons_with_bootstrap(*args) + args[4]&.delete(:id) inputs_collection(*args) do |name, value, options| radio_button(name, value, options) end diff --git a/lib/bootstrap_form/inputs/radio_button.rb b/lib/bootstrap_form/inputs/radio_button.rb index d78e0e11..9d69395f 100644 --- a/lib/bootstrap_form/inputs/radio_button.rb +++ b/lib/bootstrap_form/inputs/radio_button.rb @@ -14,7 +14,7 @@ def radio_button_with_bootstrap(name, value, *args) tag.div(**wrapper_attributes) do html = radio_button_without_bootstrap(name, value, radio_button_options(name, options)) html << radio_button_label(name, value, options) unless options[:skip_label] - html << generate_error(name) if options[:error_message] + html << generate_error(name, options[:id]) if options[:error_message] html end end @@ -28,6 +28,10 @@ def radio_button_options(name, options) radio_button_options = options.except(:class, :label, :label_class, :error_message, :help, :inline, :hide_label, :skip_label, :wrapper, :wrapper_class) radio_button_options[:class] = radio_button_classes(name, options) + if error?(name) + labelledby = options[:id].present? ? "#{options[:id]}_feedback" : field_id(name, :feedback) + radio_button_options[:aria] = { labelledby: } + end radio_button_options.merge!(required_field_options(options, name)) end diff --git a/lib/bootstrap_form/inputs/time_zone_select.rb b/lib/bootstrap_form/inputs/time_zone_select.rb index 555c2902..e174ce9b 100644 --- a/lib/bootstrap_form/inputs/time_zone_select.rb +++ b/lib/bootstrap_form/inputs/time_zone_select.rb @@ -10,7 +10,7 @@ module TimeZoneSelect def time_zone_select_with_bootstrap(method, priority_zones=nil, options={}, html_options={}) html_options = html_options.reverse_merge(control_class: "form-select") form_group_builder(method, options, html_options) do - input_with_error(method) do + input_with_error(method, options[:id]) do time_zone_select_without_bootstrap(method, priority_zones, options, html_options) end end diff --git a/test/bootstrap_checkbox_test.rb b/test/bootstrap_checkbox_test.rb index 48a8bb94..0428658c 100644 --- a/test/bootstrap_checkbox_test.rb +++ b/test/bootstrap_checkbox_test.rb @@ -543,13 +543,13 @@ class BootstrapCheckboxTest < ActionView::TestCase
- +
- + -
a box must be checked
+
a box must be checked
@@ -562,6 +562,35 @@ class BootstrapCheckboxTest < ActionView::TestCase assert_equivalent_html expected, actual end + test "collection_check_boxes renders error after last check box with specified id:" do + collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + @user.errors.add(:misc, "a box must be checked") + + expected = <<~HTML +
+ +
+ +
+ + +
+
+ + +
a box must be checked
+
+
+
+ HTML + + actual = bootstrap_form_for(@user) do |f| + f.collection_check_boxes(:misc, collection, :id, :street, { id: "custom-id" }) + end + + assert_equivalent_html expected, actual + end + test "collection_check_boxes renders data attributes" do collection = [ ["1", "Foo", { "data-city": "east" }], @@ -593,13 +622,13 @@ class BootstrapCheckboxTest < ActionView::TestCase
- +
- + -
error for test
+
error for test
@@ -611,17 +640,44 @@ class BootstrapCheckboxTest < ActionView::TestCase assert_equivalent_html expected, actual end + test "collection_check_boxes renders multiple check boxes with error correctly with specified id:" do + @user.errors.add(:misc, "error for test") + collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + expected = <<~HTML +
+ +
+ +
+ + +
+
+ + +
error for test
+
+
+
+ HTML + + actual = bootstrap_form_for(@user) do |f| + f.collection_check_boxes(:misc, collection, :id, :street, checked: collection, id: "custom-id") + end + assert_equivalent_html expected, actual + end + test "check_box renders error when asked" do @user.errors.add(:terms, "You must accept the terms.") expected = <<~HTML
- + -
You must accept the terms.
+
You must accept the terms.
HTML @@ -631,6 +687,26 @@ class BootstrapCheckboxTest < ActionView::TestCase assert_equivalent_html expected, actual end + test "check_box renders error when asked with specified id:" do + @user.errors.add(:terms, "You must accept the terms.") + expected = <<~HTML +
+
+ + + +
You must accept the terms.
+
+
+ HTML + actual = bootstrap_form_for(@user) do |f| + f.check_box(:terms, label: "I agree to the terms", error_message: true, id: "custom-id") + end + assert_equivalent_html expected, actual + end + test "check box with custom wrapper class" do expected = <<~HTML
diff --git a/test/bootstrap_fields_for_test.rb b/test/bootstrap_fields_for_test.rb index eedcef36..f79fa2a1 100644 --- a/test/bootstrap_fields_for_test.rb +++ b/test/bootstrap_fields_for_test.rb @@ -41,7 +41,7 @@ class BootstrapFieldsForTest < ActionView::TestCase
- +
diff --git a/test/bootstrap_fields_test.rb b/test/bootstrap_fields_test.rb index e456c992..efce7615 100644 --- a/test/bootstrap_fields_test.rb +++ b/test/bootstrap_fields_test.rb @@ -93,14 +93,28 @@ class BootstrapFieldsTest < ActionView::TestCase
- -
error for test
+ +
error for test
HTML assert_equivalent_html expected, bootstrap_form_for(@user) { |f| f.file_field(:misc) } end + test "file fields are wrapped correctly with error with specified id:" do + @user.errors.add(:misc, "error for test") + expected = <<~HTML +
+
+ + +
error for test
+
+
+ HTML + assert_equivalent_html expected, bootstrap_form_for(@user) { |f| f.file_field(:misc, id: "custom-id") } + end + test "errors are correctly displayed for belongs_to association fields" do @address.valid? @@ -108,14 +122,29 @@ class BootstrapFieldsTest < ActionView::TestCase
- -
must exist
+ +
must exist
HTML assert_equivalent_html expected, bootstrap_form_for(@address, url: users_path) { |f| f.text_field(:user_id) } end + test "errors are correctly displayed for belongs_to association fields with specified id:" do + @address.valid? + + expected = <<~HTML +
+
+ + +
must exist
+
+
+ HTML + assert_equivalent_html expected, bootstrap_form_for(@address, url: users_path) { |f| f.text_field(:user_id, id: "custom-id") } + end + test "hidden fields are supported" do expected = <<~HTML diff --git a/test/bootstrap_form_group_test.rb b/test/bootstrap_form_group_test.rb index 6356afea..cf526b58 100644 --- a/test/bootstrap_form_group_test.rb +++ b/test/bootstrap_form_group_test.rb @@ -187,9 +187,9 @@ class BootstrapFormGroupTest < ActionView::TestCase
$ - + .00 -
can't be blank, is too short (minimum is 5 characters) +
can't be blank, is too short (minimum is 5 characters)
@@ -434,28 +434,6 @@ class BootstrapFormGroupTest < ActionView::TestCase assert_equivalent_html expected, output end - test 'upgrade doc for form_group renders the "error" class and message correctly when object is invalid' do - @user.email = nil - assert @user.invalid? - - output = @builder.form_group :email do - html = '

Bar

'.html_safe - unless @user.errors[:email].empty? - html << tag.div(@user.errors[:email].join(", "), class: "invalid-feedback", - style: "display: block;") - end - html - end - - expected = <<~HTML -
-

Bar

-
can't be blank, is too short (minimum is 5 characters)
-
- HTML - assert_equivalent_html expected, output - end - test "upgrade doc for form_group renders check box correctly when object is invalid" do @user.errors.add(:misc, "Must select one.") @@ -471,17 +449,17 @@ class BootstrapFormGroupTest < ActionView::TestCase
- +
- +
- + -
Must select one.
+
Must select one.
@@ -509,9 +487,9 @@ class BootstrapFormGroupTest < ActionView::TestCase
- +
-
can't be blank, is too short (minimum is 5 characters)
+
can't be blank, is too short (minimum is 5 characters)
HTML output = @builder.email_field(:email, wrapper_class: "none-margin") @@ -530,8 +508,8 @@ class BootstrapFormGroupTest < ActionView::TestCase
- -
can't be blank, is too short (minimum is 5 characters)
+ +
can't be blank, is too short (minimum is 5 characters)
This is required
diff --git a/test/bootstrap_form_test.rb b/test/bootstrap_form_test.rb index 6bd2deb0..cb11863e 100644 --- a/test/bootstrap_form_test.rb +++ b/test/bootstrap_form_test.rb @@ -451,14 +451,29 @@ def warn(message, ...) expected = <<~HTML
- - + +
HTML assert_equivalent_html expected, bootstrap_form_for(@user, label_errors: true) { |f| f.text_field :email } end + test "errors display correctly and inline_errors are turned off by default when label_errors is true with specified id:" do + @user.email = nil + assert @user.invalid? + + expected = <<~HTML +
+
+ + +
+
+ HTML + assert_equivalent_html expected, bootstrap_form_for(@user, label_errors: true) { |f| f.text_field :email, id: "custom-id" } + end + test "errors display correctly and inline_errors can also be on when label_errors is true" do @user.email = nil assert @user.invalid? @@ -466,15 +481,33 @@ def warn(message, ...) expected = <<~HTML
- - -
can't be blank, is too short (minimum is 5 characters) + + +
can't be blank, is too short (minimum is 5 characters)
HTML assert_equivalent_html expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| f.text_field :email } end + test "errors display correctly and inline_errors can also be on when label_errors is true with specified id:" do + @user.email = nil + assert @user.invalid? + + expected = <<~HTML +
+
+ + +
can't be blank, is too short (minimum is 5 characters) +
+ + HTML + assert_equivalent_html expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| + f.text_field :email, id: "custom-id" + } + end + test "label error messages use humanized attribute names" do I18n.backend.store_translations(:en, activerecord: { attributes: { user: { email: "Your e-mail address" } } }) @@ -484,9 +517,9 @@ def warn(message, ...) expected = <<~HTML
- - -
can't be blank, is too short (minimum is 5 characters)
+ + +
can't be blank, is too short (minimum is 5 characters)
HTML @@ -495,6 +528,28 @@ def warn(message, ...) I18n.backend.store_translations(:en, activerecord: { attributes: { user: { email: nil } } }) end + test "label error messages use humanized attribute names with specified id:" do + I18n.backend.store_translations(:en, activerecord: { attributes: { user: { email: "Your e-mail address" } } }) + + @user.email = nil + assert @user.invalid? + + expected = <<~HTML +
+
+ + +
can't be blank, is too short (minimum is 5 characters)
+
+
+ HTML + assert_equivalent_html expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| + f.text_field :email, id: "custom-id" + } + ensure + I18n.backend.store_translations(:en, activerecord: { attributes: { user: { email: nil } } }) + end + test "alert message is wrapped correctly" do @user.email = nil assert @user.invalid? @@ -617,7 +672,7 @@ def warn(message, ...) assert @user.invalid? expected = <<~HTML -
Email can't be blank, Email is too short (minimum is 5 characters)
+
Email can't be blank, Email is too short (minimum is 5 characters)
HTML assert_equivalent_html expected, @builder.errors_on(:email) end @@ -710,8 +765,8 @@ def warn(message, ...)
- -
can't be blank, is too short (minimum is 5 characters)
+ +
can't be blank, is too short (minimum is 5 characters)
This is required
@@ -734,9 +789,9 @@ def warn(message, ...)
- +
-
can't be blank, is too short (minimum is 5 characters)
+
can't be blank, is too short (minimum is 5 characters)
This is required
@@ -756,7 +811,7 @@ def warn(message, ...)
- + This is required
@@ -800,7 +855,9 @@ def warn(message, ...) @user.email = nil assert @user.invalid? - expected = '
can\'t be blank, is too short (minimum is 5 characters)
' + expected = <<~HTML +
can't be blank, is too short (minimum is 5 characters)
+ HTML assert_equivalent_html expected, @builder.errors_on(:email, hide_attribute_name: true) end @@ -809,7 +866,11 @@ def warn(message, ...) @user.email = nil assert @user.invalid? - expected = '
Email can\'t be blank, Email is too short (minimum is 5 characters)
' + expected = <<~HTML +
+ Email can't be blank, Email is too short (minimum is 5 characters) +
+ HTML assert_equivalent_html expected, @builder.errors_on(:email, custom_class: "custom-error-class") end diff --git a/test/bootstrap_radio_button_test.rb b/test/bootstrap_radio_button_test.rb index c7543bdf..b9e82d04 100644 --- a/test/bootstrap_radio_button_test.rb +++ b/test/bootstrap_radio_button_test.rb @@ -35,11 +35,11 @@ class BootstrapRadioButtonTest < ActionView::TestCase expected = <<~HTML
- + -
error for test
+
error for test
HTML @@ -49,6 +49,25 @@ class BootstrapRadioButtonTest < ActionView::TestCase assert_equivalent_html expected, actual end + test "radio_button with error is wrapped correctly with specified id:" do + @user.errors.add(:misc, "error for test") + expected = <<~HTML +
+
+ + +
error for test
+
+
+ HTML + actual = bootstrap_form_for(@user) do |f| + f.radio_button(:misc, "1", label: "This is a radio button", error_message: true, id: "custom-id") + end + assert_equivalent_html expected, actual + end + test "radio_button disabled label is set correctly" do expected = <<~HTML
@@ -187,13 +206,13 @@ class BootstrapRadioButtonTest < ActionView::TestCase
- +
- + -
error for test
+
error for test
@@ -205,6 +224,32 @@ class BootstrapRadioButtonTest < ActionView::TestCase assert_equivalent_html expected, actual end + test "collection_radio_buttons renders multiple radios with error correctly with specified id:" do + @user.errors.add(:misc, "error for test") + collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + expected = <<~HTML +
+
+ +
+ + +
+
+ + +
error for test
+
+
+
+ HTML + + actual = bootstrap_form_for(@user) do |f| + f.collection_radio_buttons(:misc, collection, :id, :street, { id: "custom-id" }) + end + assert_equivalent_html expected, actual + end + test "collection_radio_buttons renders inline radios correctly" do collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] expected = <<~HTML diff --git a/test/bootstrap_selects_test.rb b/test/bootstrap_selects_test.rb index 13cbb2e9..a8b23599 100644 --- a/test/bootstrap_selects_test.rb +++ b/test/bootstrap_selects_test.rb @@ -42,8 +42,8 @@ def options_range(start: 1, stop: 31, selected: nil, months: false)
- -
error for test
+ +
error for test
HTML @@ -205,8 +205,8 @@ def options_range(start: 1, stop: 31, selected: nil, months: false)
- -
error for test
+ +
error for test
HTML @@ -285,8 +285,8 @@ def options_range(start: 1, stop: 31, selected: nil, months: false)
- -
error for test
+ +
error for test
HTML @@ -417,16 +417,16 @@ def options_range(start: 1, stop: 31, selected: nil, months: false)
- #{options_range(start: 2007, stop: 2017, selected: 2012)} - #{options_range(start: 1, stop: 12, selected: 2, months: true)} - #{options_range(start: 1, stop: 31, selected: 3)} -
error for test
+
error for test
@@ -435,6 +435,32 @@ def options_range(start: 1, stop: 31, selected: nil, months: false) end end + test "date selects are wrapped correctly with error with specified id:" do + @user.errors.add(:misc, "error for test") + travel_to(Time.utc(2012, 2, 3)) do + expected = <<~HTML +
+
+ +
+ + + +
error for test
+
+
+
+ HTML + assert_equivalent_html expected, bootstrap_form_for(@user) { |f| f.date_select(:misc, id: "custom-id") } + end + end + test "date selects with options are wrapped correctly" do travel_to(Time.utc(2012, 2, 3)) do expected = <<~HTML @@ -520,14 +546,14 @@ def options_range(start: 1, stop: 31, selected: nil, months: false) - #{options_range(start: '00', stop: '23', selected: '12')} : - #{options_range(start: '00', stop: '59', selected: '00')} -
error for test
+
error for test
@@ -536,6 +562,33 @@ def options_range(start: 1, stop: 31, selected: nil, months: false) end end + test "time selects are wrapped correctly with error with specified id:" do + @user.errors.add(:misc, "error for test") + travel_to(Time.utc(2012, 2, 3, 12, 0, 0)) do + expected = <<~HTML +
+
+ +
+ + + + + : + +
error for test
+
+
+
+ HTML + assert_equivalent_html expected, bootstrap_form_for(@user) { |f| f.time_select(:misc, id: "custom-id") } + end + end + test "time selects with options are wrapped correctly" do travel_to(Time.utc(2012, 2, 3, 12, 0, 0)) do expected = <<~HTML @@ -624,24 +677,24 @@ def options_range(start: 1, stop: 31, selected: nil, months: false)
- #{options_range(start: 2007, stop: 2017, selected: 2012)} - #{options_range(start: 1, stop: 12, selected: 2, months: true)} - #{options_range(start: 1, stop: 31, selected: 3)} — - #{options_range(start: '00', stop: '23', selected: '12')} : - #{options_range(start: '00', stop: '59', selected: '00')} -
error for test
+
error for test
@@ -650,6 +703,40 @@ def options_range(start: 1, stop: 31, selected: nil, months: false) end end + test "datetime selects are wrapped correctly with error with specified id:" do + @user.errors.add(:misc, "error for test") + travel_to(Time.utc(2012, 2, 3, 12, 0, 0)) do + expected = <<~HTML +
+
+ +
+ + + + — + + : + +
error for test
+
+
+
+ HTML + assert_equivalent_html expected, bootstrap_form_for(@user) { |f| f.datetime_select(:misc, id: "custom-id") } + end + end + test "datetime selects with options are wrapped correctly" do travel_to(Time.utc(2012, 2, 3, 12, 0, 0)) do expected = <<~HTML diff --git a/test/special_form_class_models_test.rb b/test/special_form_class_models_test.rb index 98550b39..d2857ea8 100644 --- a/test/special_form_class_models_test.rb +++ b/test/special_form_class_models_test.rb @@ -79,9 +79,9 @@ def user_klass.model_name
- +
-
can't be blank
+
can't be blank
HTML assert_equivalent_html expected, @builder.text_field(:password)