diff --git a/CHANGELOG.md b/CHANGELOG.md index 05327c847..92b569a80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ Bugfixes: Features: - Your contribution here! + * Support for Rails 5.1 `form_with`. + * [#325](https://github.com/bootstrap-ruby/rails-bootstrap-forms/pull/325): Support :prepend and :append for the `select` helper - [@donv](https://github.com/donv). + ## [2.7.0][] (2017-04-21) diff --git a/README.md b/README.md index c1404a130..629b85ca8 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ twitter bootstrap-style forms into your rails application. ## Requirements * Ruby 1.9+ -* Rails 4.0+ +* Rails 4.0+ (Rails 5.1+ for `bootstrap_form_with`) * Twitter Bootstrap 3.0+ ## Installation @@ -32,6 +32,161 @@ Then require the CSS in your `application.css` file: ## Usage +### Rails >= 5.1 + +To get started, just use the `bootstrap_form_with` helper +in place of `form_with`. Here's an example: + +```erb +<%= bootstrap_form_with(model: @user, local: true) do |f| %> + <%= f.email_field :email %> + <%= f.password_field :password %> + <%= f.check_box :remember_me %> + <%= f.submit "Log In" %> +<% end %> +``` + +This generates: + +```html +
+ +
+ + +
+
+ + + A good password should be at least six characters long +
+
+ +
+ +
+``` + +If your form is not backed by a model, use `bootstrap_form_with` like this: + +```erb +<%= bootstrap_form_with url: '/subscribe', local: true do |f| %> + <%= f.email_field :email, value: 'name@example.com' %> + <%= f.submit %> +<% end %> +``` + +```html +
+ +
+ + +
+ +
+``` + +#### Important Differences Between `form_with` and `form_for` + +Rails 5.1 introduced `form_with`, +which unifies the functionality previously found in `form_for` and `form_tag`. +`form_for` and `form_tag` will be deprecated in a future version of Rails, +so new applications should use `bootstrap_form_with`. + +`form_with` is different compared to `form_for` and `form_tag`. +`bootstrap_form_width` basically just wraps `form_with` +and adds some functionality, +and so the different behaviour of `form_with` +is refelected in `bootstrap_form_with` +compared to `bootstrap_form_for` +and `bootstrap_form_tag`. + +##### Ajax by Default +`form_with` defaults to submitting forms via Javascript XHR calls, +like `form_for` or `form_tag` would do if you specified `remote: true`. +If you want the browser to submit the request +the same way `form_for` and `form_tag` would do by default, +you need to specify `local: true` as an option to `form_with`. + +##### No Default DOM IDs +When used with the builder (variable) yielded by `form_with`, +the Rails field helpers do not generate a default DOM id. +Because `bootstrap_form_width` just wraps and adds some functionality +to `form_with`, +the `bootstrap_form` field helpers also do not generate a default DOM id. +This should not affect your application, +but it might affect automated testing if you're using Capybara or similar tools, +if you wrote actions or tests that selected on the DOM id of an element. + +There is a Rails [pull request](https://github.com/rails/rails/pull/29439) +to enable the `skip_default_ids: false` option to reproduce +the old default DOM id behaviour in `form_with`. +This option will be supported by `bootstrap_form_with` +if/when the PR is merged into Rails. + +You can also specify the id explicitly in most cases: + +```erb +<%= bootstrap_form_with(model: @user, local: true) do |f| %> + <%= f.email_field :email %> + <%= f.password_field :password, id: :password %> + <%= f.check_box :remember_me, id: :remember %> + <%= f.submit "Log In" %> +<% end %> +``` + +generates: + +```html +
+ +
+ + +
+
+ + + A good password should be at least six characters long +
+
+
+ +
+``` + +The current exception to specifying an id are for the "collection" helpers. +Because they generate multiple elements that require multiple ids, +you need to rely on the default id generation. + +Another result of the lack of default DOM ids +is that text fields AND OTHERS TBD +are no longer linked to their label. +This should not affect your application, +but it might affect automated testing using Capybara or similar tools, +if you wrote actions or tests that selected on the DOM id of an element. + +##### User `fields` Instead Of `fields_for` In Nested Forms +For nested forms, use `fields` instead of `fields_for`. + +##### No Default Classes +Finally, `bootstrap_form_with` doesn't attach a default class +to the form. +If you attached styling to the DOM class that `form_for` added to the form element, +you'll have to add your own code to attach the appropriate class. + +#### Nested Forms with `bootstrap_form_with` + +This hasn't been tested yet. + +### Rails < 5.1 + To get started, just use the `bootstrap_form_for` helper. Here's an example: ```erb @@ -55,13 +210,13 @@ This generates the following HTML: -
+
- + ``` @@ -209,7 +364,7 @@ This automatically adds the `has-feedback` class to the `form-group`: ```html
- +
@@ -227,7 +382,7 @@ You can also prepend and append buttons. Note: The buttons must contain the `btn` class to generate the correct markup. ```erb -<%= f.text_field :search, append: link_to("Go", "#", class: "btn btn-default") %> +<%= f.text_field :search, append: link_to("Go", "#", class: "btn btn-secondary") %> ``` To add a class to the input group wrapper, use `:input_group_class` option. @@ -249,7 +404,7 @@ Which produces the following output: ```erb
- +
``` @@ -330,7 +485,7 @@ Here's the output: ```html
- +

test@email.com

@@ -355,7 +510,7 @@ this defining these selects as `inline-block` and a width of `auto`. ### Submit Buttons -The `btn btn-default` css classes are automatically added to your submit +The `btn btn-secondary` css classes are automatically added to your submit buttons. ```erb @@ -468,10 +623,10 @@ error will be displayed below the field. Rails normally wraps the fields in a div (field_with_errors), but this behavior is suppressed. Here's an example: ```html -
- +
+ - can't be blank +
``` diff --git a/lib/bootstrap_form/form_builder.rb b/lib/bootstrap_form/form_builder.rb index e127c7bb3..0f6665d8f 100644 --- a/lib/bootstrap_form/form_builder.rb +++ b/lib/bootstrap_form/form_builder.rb @@ -9,9 +9,9 @@ class FormBuilder < ActionView::Helpers::FormBuilder attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :label_errors, :acts_like_form_tag FIELD_HELPERS = %w{color_field date_field datetime_field datetime_local_field - email_field month_field number_field password_field phone_field - range_field search_field telephone_field text_area text_field time_field - url_field week_field} + email_field month_field number_field password_field phone_field + range_field search_field telephone_field text_area text_field time_field + url_field week_field} DATE_SELECT_HELPERS = %w{date_select time_select datetime_select} @@ -114,7 +114,9 @@ def time_zone_select_with_bootstrap(method, priority_zones = nil, options = {}, def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_value = "0", &block) options = options.symbolize_keys! + label_for = label_for_from_options(options) check_box_options = options.except(:label, :label_class, :help, :inline) + check_box_options[:class] = ["form-check-input", check_box_options[:class]].compact.join(' ') html = check_box_without_bootstrap(name, check_box_options, checked_value, unchecked_value) label_content = block_given? ? capture(&block) : options[:label] @@ -134,10 +136,10 @@ def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_ if options[:inline] label_class = " #{label_class}" if label_class - label(label_name, html, class: "checkbox-inline#{disabled_class}#{label_class}") + label(label_name, html, label_for.merge(class: "form-check-inline#{disabled_class}#{label_class}")) else - content_tag(:div, class: "checkbox#{disabled_class}") do - label(label_name, html, class: label_class) + content_tag(:div, class: "form-check#{disabled_class}") do + label(label_name, html, label_for.merge(class: ["form-check-label", label_class].compact.join(" "))) end end end @@ -146,6 +148,7 @@ def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_ def radio_button_with_bootstrap(name, value, *args) options = args.extract_options!.symbolize_keys! + label_for = label_for_from_options(options) args << options.except(:label, :label_class, :help, :inline) html = radio_button_without_bootstrap(name, value, *args) + " " + options[:label] @@ -155,10 +158,10 @@ def radio_button_with_bootstrap(name, value, *args) if options[:inline] label_class = " #{label_class}" if label_class - label(name, html, class: "radio-inline#{disabled_class}#{label_class}", value: value) + label(name, html, label_for.merge(class: "radio-inline#{disabled_class}#{label_class}", value: value)) else content_tag(:div, class: "radio#{disabled_class}") do - label(name, html, value: value, class: label_class) + label(name, html, label_for.merge(value: value, class: label_class)) end end end @@ -170,7 +173,7 @@ def collection_check_boxes_with_bootstrap(*args) options[:multiple] = true check_box(name, options, value, nil) end - hidden_field(args.first,{value: "", multiple: true}).concat(html) + hidden_field(args.first, {value: "", multiple: true}).concat(html) end bootstrap_method_alias :collection_check_boxes @@ -198,6 +201,7 @@ def form_group(*args, &block) name = args.first options[:class] = ["form-group", options[:class]].compact.join(' ') + options[:class] << " row" if get_group_layout(options[:layout]) == :horizontal options[:class] << " #{error_class}" if has_error?(name) options[:class] << " #{feedback_class}" if options[:icon] @@ -221,7 +225,10 @@ def form_group(*args, &block) end def fields_for_with_bootstrap(record_name, record_object = nil, fields_options = {}, &block) - fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options? + if record_object.is_a?(Hash) && record_object.extractable_options? + fields_options = record_object + record_object = nil + end fields_options[:layout] ||= options[:layout] fields_options[:label_col] = fields_options[:label_col].present? ? "#{fields_options[:label_col]} #{label_class}" : options[:label_col] fields_options[:control_col] ||= options[:control_col] @@ -263,11 +270,11 @@ def control_class end def label_class - "control-label" + "form-control-label" end def error_class - "has-error" + "has-danger" end def feedback_class @@ -295,11 +302,11 @@ def required_attribute?(obj, attribute) end has_presence_validator = target_validators.include?( - ActiveModel::Validations::PresenceValidator) + ActiveModel::Validations::PresenceValidator) if defined? ActiveRecord::Validations::PresenceValidator has_presence_validator |= target_validators.include?( - ActiveRecord::Validations::PresenceValidator) + ActiveRecord::Validations::PresenceValidator) end has_presence_validator @@ -308,11 +315,13 @@ def required_attribute?(obj, attribute) def form_group_builder(method, options, html_options = nil) options.symbolize_keys! html_options.symbolize_keys! if html_options + options[:id] = html_options[:id] if html_options && @options[:skip_default_ids] # Add control_class; allow it to be overridden by :control_class option css_options = html_options || options control_classes = css_options.delete(:control_class) { control_class } css_options[:class] = [control_classes, css_options[:class]].compact.join(" ") + css_options[:class] << " form-control-danger" if has_error?(method) options = convert_form_tag_options(method, options) if acts_like_form_tag @@ -350,11 +359,11 @@ def form_group_builder(method, options, html_options = nil) label_text ||= options.delete(:label) end - form_group_options.merge!(label: { + form_group_options[:label] = { text: label_text, class: label_class, skip_required: options.delete(:skip_required) - }) + } end form_group(method, form_group_options) do @@ -363,13 +372,15 @@ def form_group_builder(method, options, html_options = nil) end def convert_form_tag_options(method, options = {}) - options[:name] ||= method - options[:id] ||= method + unless @options[:skip_default_ids] + options[:name] ||= method + options[:id] ||= method + end options end def generate_label(id, name, options, custom_label_col, group_layout) - options[:for] = id if acts_like_form_tag + add_for_option_if_needed!(options, id) classes = [options[:class], label_class] classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal unless options.delete(:skip_required) @@ -385,16 +396,36 @@ def generate_label(id, name, options, custom_label_col, group_layout) else label(name, options[:text], options.except(:text)) end + end + def add_for_option_if_needed!(options, id) + options[:for] = id if acts_like_form_tag + options[:for] ||= id if @options[:skip_default_ids] + end + + def label_for_from_options(options) + if !@options[:skip_default_ids] + {} + elsif options.key?(:for) + { for: options[:for] } + elsif options.key?(:id) + { for: options[:id] } + else + { for: nil } + end end def generate_help(name, help_text) - help_text = get_error_messages(name) if has_error?(name) && inline_errors - return if help_text === false + if has_error?(name) && inline_errors + help_text = get_error_messages(name) + help_klass = 'form-control-feedback' + end + return if help_text == false + help_klass ||= 'form-text text-muted' help_text ||= get_help_text_by_i18n_key(name) - content_tag(:span, help_text, class: 'help-block') if help_text.present? + content_tag(:span, help_text, class: help_klass) if help_text.present? end def generate_icon(icon) @@ -448,6 +479,5 @@ def get_help_text_by_i18n_key(name) help_text end end - end end diff --git a/lib/bootstrap_form/helper.rb b/lib/bootstrap_form/helper.rb index ee73c9016..576723394 100644 --- a/lib/bootstrap_form/helper.rb +++ b/lib/bootstrap_form/helper.rb @@ -7,19 +7,7 @@ module Helper def bootstrap_form_for(object, options = {}, &block) options.reverse_merge!({builder: BootstrapForm::FormBuilder}) - options[:html] ||= {} - options[:html][:role] ||= 'form' - - layout = case options[:layout] - when :inline - "form-inline" - when :horizontal - "form-horizontal" - end - - if layout - options[:html][:class] = [options[:html][:class], layout].compact.join(" ") - end + options = process_options(options) temporarily_disable_field_error_proc do form_for(object, options, &block) @@ -32,6 +20,31 @@ def bootstrap_form_tag(options = {}, &block) bootstrap_form_for("", options, &block) end + def bootstrap_form_with(options = {}, &block) + options.reverse_merge!(builder: BootstrapForm::FormBuilder) + + options = process_options(options) + + temporarily_disable_field_error_proc do + form_with(options, &block) + end + end + + private + + def process_options(options) + options[:html] ||= {} + options[:html][:role] ||= 'form' + + if options[:layout] == :inline + options[:html][:class] = [options[:html][:class], 'form-inline'].compact.join(' ') + end + + options + end + + public + def temporarily_disable_field_error_proc original_proc = ActionView::Base.field_error_proc ActionView::Base.field_error_proc = proc { |input, instance| input } diff --git a/lib/bootstrap_form/helpers/bootstrap.rb b/lib/bootstrap_form/helpers/bootstrap.rb index 988b16280..58b31d76e 100644 --- a/lib/bootstrap_form/helpers/bootstrap.rb +++ b/lib/bootstrap_form/helpers/bootstrap.rb @@ -2,7 +2,7 @@ module BootstrapForm module Helpers module Bootstrap def submit(name = nil, options = {}) - options.reverse_merge! class: 'btn btn-default' + options.reverse_merge! class: 'btn btn-secondary' super(name, options) end diff --git a/test/bootstrap_checkbox_test.rb b/test/bootstrap_checkbox_test.rb index 0d2832690..da2df251c 100644 --- a/test/bootstrap_checkbox_test.rb +++ b/test/bootstrap_checkbox_test.rb @@ -8,74 +8,74 @@ def setup end test "check_box is wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms') end test "disabled check_box has proper wrapper classes" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms', disabled: true) end test "check_box label allows html" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.check_box(:terms, label: %{I agree to the terms}.html_safe) end test "check_box accepts a block to define the label" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.check_box(:terms) { "I agree to the terms" } end test "check_box accepts a custom label class" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.check_box(:terms, label_class: 'btn') end test "check_box responds to checked_value and unchecked_value arguments" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.check_box(:terms, {label: 'I agree to the terms'}, 'yes', 'no') end test "inline checkboxes" do - expected = %{} + expected = %{} assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms', inline: true) end test "disabled inline check_box" do - expected = %{} + expected = %{} assert_equivalent_xml expected, @builder.check_box(:terms, label: 'I agree to the terms', inline: true, disabled: true) end test "inline checkboxes with custom label class" do - expected = %{} + expected = %{} assert_equivalent_xml expected, @builder.check_box(:terms, inline: true, label_class: 'btn') end test 'collection_check_boxes renders the form_group correctly' do collection = [Address.new(id: 1, street: 'Foobar')] - expected = %{
With a help!
} + expected = %{
With a help!
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, label: 'This is a checkbox collection', help: 'With a help!') end test 'collection_check_boxes renders multiple checkboxes correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street) end test 'collection_check_boxes renders inline checkboxes correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, inline: true) end test 'collection_check_boxes renders with checked option correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: 1) assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection.first) @@ -83,7 +83,7 @@ def setup test 'collection_check_boxes renders with multiple checked options correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: [1, 2]) assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection) @@ -91,42 +91,42 @@ def setup test 'collection_check_boxes sanitizes values when generating label `for`' do collection = [Address.new(id: 1, street: 'Foo St')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :street, :street) end test 'collection_check_boxes renders multiple checkboxes with labels defined by Proc :text_method correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, Proc.new { |a| a.street.reverse }) end test 'collection_check_boxes renders multiple checkboxes with values defined by Proc :value_method correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street) end test 'collection_check_boxes renders multiple checkboxes with labels defined by lambda :text_method correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, :id, lambda { |a| a.street.reverse }) end test 'collection_check_boxes renders multiple checkboxes with values defined by lambda :value_method correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street) end test 'collection_check_boxes renders with checked option correctly with Proc :value_method' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, checked: "address_1") assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, checked: collection.first) @@ -134,7 +134,7 @@ def setup test 'collection_check_boxes renders with multiple checked options correctly with lambda :value_method' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, checked: ["address_1", "address_2"]) assert_equivalent_xml expected, @builder.collection_check_boxes(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, checked: collection) diff --git a/test/bootstrap_fields_test.rb b/test/bootstrap_fields_test.rb index 3eaec8ece..b7d9445c9 100644 --- a/test/bootstrap_fields_test.rb +++ b/test/bootstrap_fields_test.rb @@ -8,32 +8,32 @@ def setup end test "color fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.color_field(:misc) end test "date fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.date_field(:misc) end test "date time fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.datetime_field(:misc) end test "date time local fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.datetime_local_field(:misc) end test "email fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.email_field(:misc) end test "file fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.file_field(:misc) end @@ -43,58 +43,58 @@ def setup end test "month local fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.month_field(:misc) end test "number fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.number_field(:misc) end test "password fields are wrapped correctly" do - expected = %{
A good password should be at least six characters long
} + expected = %{
A good password should be at least six characters long
} assert_equivalent_xml expected, @builder.password_field(:password) end test "phone/telephone fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.phone_field(:misc) assert_equivalent_xml expected, @builder.telephone_field(:misc) end test "range fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.range_field(:misc) end test "search fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.search_field(:misc) end test "text areas are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_area(:comments) end test "text fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email) end test "time fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.time_field(:misc) end test "url fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.url_field(:misc) end test "week fields are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.week_field(:misc) end @@ -107,7 +107,7 @@ def setup end end - expected = %{
} + expected = %{
} assert_equivalent_xml expected, output end @@ -120,7 +120,7 @@ def setup end end - expected = %{
} + expected = %{
} assert_equivalent_xml expected, output end @@ -133,7 +133,7 @@ def setup end end - expected = %{
} + expected = %{
} assert_equivalent_xml expected, output end @@ -146,7 +146,7 @@ def setup end end - expected = %{
} + expected = %{
} assert_equivalent_xml expected, output end end diff --git a/test/bootstrap_form_group_test.rb b/test/bootstrap_form_group_test.rb index 26a0a62fb..6c1f6d115 100644 --- a/test/bootstrap_form_group_test.rb +++ b/test/bootstrap_form_group_test.rb @@ -8,32 +8,32 @@ def setup end test "changing the label text via the label option parameter" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, label: 'Email Address') end test "changing the label text via the html_options label hash" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, label: {text: 'Email Address'}) end test "hiding a label" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, hide_label: true) end test "adding a custom label class via the label_class parameter" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, label_class: 'btn') end test "adding a custom label class via the html_options label hash" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, label: {class: 'btn'}) end test "adding a custom label and changing the label text via the html_options label hash" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, label: {class: 'btn', text: "Email Address"}) end @@ -43,51 +43,51 @@ def setup end test "preventing a label from having the required class" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, skip_required: true) end test "adding prepend text" do - expected = %{
@
} + expected = %{
@
} assert_equivalent_xml expected, @builder.text_field(:email, prepend: '@') end test "adding append text" do - expected = %{
.00
} + expected = %{
.00
} assert_equivalent_xml expected, @builder.text_field(:email, append: '.00') end test "append and prepend button" do - prefix = %{
} + prefix = %{
} field = %{} - button = %{Click} + button = %{Click} suffix = %{
} after_button = prefix + field + button + suffix before_button = prefix + button + field + suffix both_button = prefix + button + field + button + suffix - button_src = link_to("Click", "#", class: "btn btn-default") + button_src = link_to("Click", "#", class: "btn btn-secondary") assert_equivalent_xml after_button, @builder.text_field(:email, append: button_src) assert_equivalent_xml before_button, @builder.text_field(:email, prepend: button_src) assert_equivalent_xml both_button, @builder.text_field(:email, append: button_src, prepend: button_src) end test "adding both prepend and append text" do - expected = %{
$.00
} + expected = %{
$.00
} assert_equivalent_xml expected, @builder.text_field(:email, prepend: '$', append: '.00') end test "help messages for default forms" do - expected = %{
This is required
} + expected = %{
This is required
} assert_equivalent_xml expected, @builder.text_field(:email, help: 'This is required') end test "help messages for horizontal forms" do - expected = %{
This is required
} + expected = %{
This is required
} assert_equivalent_xml expected, @horizontal_builder.text_field(:email, help: "This is required") end test "help messages to look up I18n automatically" do - expected = %{
A good password should be at least six characters long
} + expected = %{
A good password should be at least six characters long
} assert_equivalent_xml expected, @builder.text_field(:password) end @@ -110,7 +110,7 @@ def setup end test "help messages to ignore translation when user disables help" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:password, help: false) end @@ -119,7 +119,7 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

} + expected = %{

Bar

} assert_equivalent_xml expected, output end @@ -128,7 +128,7 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

} + expected = %{

Bar

} assert_equivalent_xml expected, output end @@ -137,7 +137,7 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

} + expected = %{

Bar

} assert_equivalent_xml expected, output end @@ -146,7 +146,7 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

} + expected = %{

Bar

} assert_equivalent_xml expected, output end @@ -155,7 +155,7 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

} + expected = %{

Bar

} assert_equivalent_xml expected, output end @@ -164,7 +164,7 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

} + expected = %{

Bar

} assert_equivalent_xml expected, output end @@ -176,12 +176,12 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

can't be blank, is too short (minimum is 5 characters)
} + expected = %{

Bar

} assert_equivalent_xml expected, output end test "adds class to wrapped form_group by a field" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.search_field(:misc, wrapper_class: 'none-margin') end @@ -189,7 +189,7 @@ def setup @user.email = nil @user.valid? - expected = %{
can't be blank, is too short (minimum is 5 characters)
} + expected = %{
} assert_equivalent_xml expected, @builder.email_field(:email, wrapper_class: 'none-margin') end @@ -201,7 +201,7 @@ def setup f.text_field(:email, help: 'This is required', wrapper_class: 'none-margin') end - expected = %{
can't be blank, is too short (minimum is 5 characters)
} + expected = %{
} assert_equivalent_xml expected, output end @@ -210,7 +210,7 @@ def setup @horizontal_builder.submit end - expected = %{
} + expected = %{
} assert_equivalent_xml expected, output end @@ -219,12 +219,12 @@ def setup @horizontal_builder.submit end - expected = %{
} + expected = %{
} assert_equivalent_xml expected, output end test "adding an icon to a field" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.email_field(:misc, icon: 'ok') end @@ -236,17 +236,17 @@ def setup output = output + @horizontal_builder.text_field(:email) - expected = %{
Hallo
} + expected = %{
Hallo
} assert_equivalent_xml expected, output end test "adds data-attributes (or any other options) to wrapper" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.search_field(:misc, wrapper: { data: { foo: 'bar' } }) end test "passing options to a form control get passed through" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.text_field(:email, autofocus: true) end @@ -255,12 +255,12 @@ def setup nil end - expected = %{
} + expected = %{
} assert_equivalent_xml expected, output end test "custom form group layout option" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email, layout: :inline } end @@ -270,7 +270,7 @@ def setup %{

Bar

}.html_safe end - expected = %{

Bar

} + expected = %{

Bar

} assert_equivalent_xml expected, output end @@ -278,12 +278,12 @@ def setup frozen_horizontal_builder = BootstrapForm::FormBuilder.new(:user, @user, self, { layout: :horizontal, label_col: "col-sm-3".freeze, control_col: "col-sm-9".freeze }) output = frozen_horizontal_builder.form_group { 'test' } - expected = %{
test
} + expected = %{
test
} assert_equivalent_xml expected, output end test ":input_group_class should apply to input-group" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.email_field(:email, append: @builder.primary('Subscribe'), input_group_class: 'input-group-lg') end end diff --git a/test/bootstrap_form_test.rb b/test/bootstrap_form_test.rb index e4df02c60..7e0d69683 100644 --- a/test/bootstrap_form_test.rb +++ b/test/bootstrap_form_test.rb @@ -18,12 +18,12 @@ def setup end test "horizontal-style forms" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email } end test "existing styles aren't clobbered when specifying a form style" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal, html: { class: "my-style" }) { |f| f.email_field :email } end @@ -33,20 +33,20 @@ def setup end test "bootstrap_form_tag acts like a form tag" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_tag(url: '/users') { |f| f.text_field :email, label: "Your Email" } end test "bootstrap_form_tag does not clobber custom options" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_tag(url: '/users') { |f| f.text_field :email, name: 'NAME', id: "ID" } end test "bootstrap_form_tag allows an empty name for checkboxes" do checkbox = if ::Rails::VERSION::STRING >= '5.1' - %{
} + %{
} else - %{
} + %{
} end expected = %{
#{checkbox}
} assert_equivalent_xml expected, bootstrap_form_tag(url: '/users') { |f| f.check_box :misc } @@ -56,7 +56,7 @@ def setup @user.email = nil @user.valid? - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_for(@user, label_errors: true) { |f| f.text_field :email } end @@ -64,7 +64,7 @@ def setup @user.email = nil @user.valid? - expected = %{
can't be blank, is too short (minimum is 5 characters)
} + expected = %{
can't be blank, is too short (minimum is 5 characters)
} assert_equivalent_xml expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| f.text_field :email } end @@ -74,7 +74,7 @@ def setup @user.email = nil @user.valid? - expected = %{
can't be blank, is too short (minimum is 5 characters)
} + expected = %{
can't be blank, is too short (minimum is 5 characters)
} assert_equivalent_xml expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| f.text_field :email } I18n.backend.store_translations(:en, {activerecord: {attributes: {user: {email: nil}}}}) @@ -147,17 +147,17 @@ def setup end test "custom label width for horizontal forms" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email, label_col: 'col-sm-1' } end test "offset for form group without label respects label width for horizontal forms" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal, label_col: 'col-md-2', control_col: 'col-md-10') { |f| f.form_group { f.submit } } end test "custom input width for horizontal forms" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email, control_col: 'col-sm-5' } end @@ -169,7 +169,7 @@ def setup f.text_field(:email, help: 'This is required') end - expected = %{
can't be blank, is too short (minimum is 5 characters)
} + expected = %{
} assert_equivalent_xml expected, output end @@ -181,7 +181,7 @@ def setup f.text_field(:email, help: 'This is required') end - expected = %{
can't be blank, is too short (minimum is 5 characters)
} + expected = %{
} assert_equivalent_xml expected, output end @@ -193,13 +193,13 @@ def setup f.text_field(:email, help: 'This is required') end - expected = %{
This is required
} + expected = %{
This is required
} assert_equivalent_xml expected, output end test "allows the form object to be nil" do builder = BootstrapForm::FormBuilder.new :other_model, nil, self, {} - expected = %{
} + expected = %{
} assert_equivalent_xml expected, builder.text_field(:email) end diff --git a/test/bootstrap_form_with_checkbox_test.rb b/test/bootstrap_form_with_checkbox_test.rb new file mode 100644 index 000000000..e8ee2a576 --- /dev/null +++ b/test/bootstrap_form_with_checkbox_test.rb @@ -0,0 +1,162 @@ +if ::Rails::VERSION::STRING >= "5.1" + require "test_helper" + + class BootstrapFormWithCheckboxTest < ActionView::TestCase + include BootstrapForm::Helper + + def setup + setup_test_fixture + end + + test "check_box is wrapped correctly" do + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms") + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms", id: "custom_id") + end + + test "disabled check_box has proper wrapper classes" do + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms", disabled: true) + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms", disabled: true, id: "custom_id") + end + + test "check_box label allows html" do + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: %(I agree to the terms).html_safe) + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: %(I agree to the terms).html_safe, id: "custom_id") + end + + test "check_box accepts a block to define the label" do + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms) { "I agree to the terms" } + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, id: "custom_id") { "I agree to the terms" } + end + + test "check_box accepts a custom label class" do + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label_class: "btn") + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label_class: "btn", id: "custom_id") + end + + test "check_box responds to checked_value and unchecked_value arguments" do + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, { label: "I agree to the terms" }, "yes", "no") + expected = %(
) + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, { label: "I agree to the terms", id: "custom_id" }, "yes", "no") + end + + test "inline checkboxes" do + expected = %() + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms", inline: true) + expected = %() + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms", inline: true, id: "custom_id") + end + + test "disabled inline check_box" do + expected = %() + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms", inline: true, disabled: true) + expected = %() + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, label: "I agree to the terms", inline: true, disabled: true, id: "custom_id") + end + + test "inline checkboxes with custom label class" do + expected = %() + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, inline: true, label_class: "btn") + expected = %() + assert_equivalent_xml expected, @form_with_builder.check_box(:terms, inline: true, label_class: "btn", id: "custom_id") + end + + # test "collection_check_boxes renders the form_group correctly" do + # collection = [Address.new(id: 1, street: "Foobar")] + # expected = %(
With a help!
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, :street, label: "This is a checkbox collection", help: "With a help!") + # end + # + # test "collection_check_boxes renders multiple checkboxes correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, :street) + # end + # + # test "collection_check_boxes renders inline checkboxes correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, :street, inline: true) + # end + # + # test "collection_check_boxes renders with checked option correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, :street, checked: 1) + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection.first) + # end + # + # test "collection_check_boxes renders with multiple checked options correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, :street, checked: [1, 2]) + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, :street, checked: collection) + # end + # + # test "collection_check_boxes sanitizes values when generating label `for`" do + # collection = [Address.new(id: 1, street: "Foo St")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :street, :street) + # end + # + # test "collection_check_boxes renders multiple checkboxes with labels defined by Proc :text_method correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, proc { |a| a.street.reverse }) + # end + # + # test "collection_check_boxes renders multiple checkboxes with values defined by Proc :value_method correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, proc { |a| "address_#{a.id}" }, :street) + # end + # + # test "collection_check_boxes renders multiple checkboxes with labels defined by lambda :text_method correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, :id, ->(a) { a.street.reverse }) + # end + # + # test "collection_check_boxes renders multiple checkboxes with values defined by lambda :value_method correctly" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, ->(a) { "address_#{a.id}" }, :street) + # end + # + # test "collection_check_boxes renders with checked option correctly with Proc :value_method" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, proc { |a| "address_#{a.id}" }, :street, checked: "address_1") + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, proc { |a| "address_#{a.id}" }, :street, checked: collection.first) + # end + # + # test "collection_check_boxes renders with multiple checked options correctly with lambda :value_method" do + # collection = [Address.new(id: 1, street: "Foo"), Address.new(id: 2, street: "Bar")] + # expected = %(
) + # + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, ->(a) { "address_#{a.id}" }, :street, checked: %w(address_1 address_2)) + # assert_equivalent_xml expected, @form_with_builder.collection_check_boxes(:misc, collection, ->(a) { "address_#{a.id}" }, :street, checked: collection) + # end + end +end diff --git a/test/bootstrap_form_with_fields_test.rb b/test/bootstrap_form_with_fields_test.rb new file mode 100644 index 000000000..ab6e3a3a0 --- /dev/null +++ b/test/bootstrap_form_with_fields_test.rb @@ -0,0 +1,132 @@ +if ::Rails::VERSION::STRING >= '5.1' + require 'test_helper' + + class BootstrapFormWithFieldsTest < ActionView::TestCase + include BootstrapForm::Helper + + def setup + setup_test_fixture + end + + # Tests for field types that have explicit labels, and therefore are + # potentially affected by the lack of default DOM ids from `form_with`. + + test "form_with text areas are wrapped correctly" do + expected = %{
} + # puts "Rails: #{ActionView::Helpers::FormBuilder.new(:user, @user, self, {}).text_area(:comments)}" + assert_equivalent_xml expected, @form_with_builder.text_area(:comments) + expected = %{
} + # Doesn't the new Rails way mean everyone has to know how to generate Rails field IDs? + assert_equivalent_xml expected, @form_with_builder.text_area(:comments, id: :user_comments) + end + + test "form_with password fields are wrapped correctly" do + expected = %{
A good password should be at least six characters long
} + assert_equivalent_xml expected, @form_with_builder.password_field(:password) + expected = %{
A good password should be at least six characters long
} + assert_equivalent_xml expected, @form_with_builder.password_field(:password, id: :user_password) + end + + test "form_with file fields are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.file_field(:misc) + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.file_field(:misc, id: :user_misc) + end + + test "form_with text fields are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.text_field(:email) + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.text_field(:email, id: :user_email) + end + + test "bootstrap_form_with helper works for associations" do + @user.address = Address.new(street: '123 Main Street') + + output = bootstrap_form_with(model: @user, local: true) do |f| + f.fields :address do |af| + af.text_field(:street) + end + end + + expected = %{
} + assert_equivalent_xml expected, output + + output = bootstrap_form_with(model: @user, local: true) do |f| + f.fields :address do |af| + af.text_field(:street, id: :user_address_attributes_street) + end + end + + expected = %{
} + assert_equivalent_xml expected, output + end + + test "bootstrap_form_with helper works for serialized hash attributes" do + @user.preferences = { favorite_color: "cerulean" } + + output = bootstrap_form_with(model: @user, local: true) do |f| + f.fields :preferences do |builder| + builder.text_field :favorite_color, value: @user.preferences[:favorite_color] + end + end + + expected = %{
} + assert_equivalent_xml expected, output + + output = bootstrap_form_with(model: @user, local: true) do |f| + f.fields :preferences do |builder| + builder.text_field :favorite_color, value: @user.preferences[:favorite_color], id: :user_preferences_favorite_color + end + end + + expected = %{
} + assert_equivalent_xml expected, output + end + + test "form_with fields correctly passes horizontal style from parent builder" do + @user.address = Address.new(street: '123 Main Street') + + output = bootstrap_form_with(model: @user, layout: :horizontal, label_col: 'col-sm-2', control_col: 'col-sm-10', local: true) do |f| + f.fields :address do |af| + af.text_field(:street) + end + end + + expected = %{
} + assert_equivalent_xml expected, output + + output = bootstrap_form_with(model: @user, layout: :horizontal, label_col: 'col-sm-2', control_col: 'col-sm-10', local: true) do |f| + f.fields :address do |af| + af.text_field(:street, id: :user_address_attributes_street) + end + end + + expected = %{
} + assert_equivalent_xml expected, output + end + + test "form_with fields correctly passes inline style from parent builder" do + @user.address = Address.new(street: '123 Main Street') + + output = bootstrap_form_with(model: @user, layout: :inline, local: true) do |f| + f.fields :address do |af| + af.text_field(:street) + end + end + + expected = %{
} + assert_equivalent_xml expected, output + + output = bootstrap_form_with(model: @user, layout: :inline, local: true) do |f| + f.fields :address do |af| + af.text_field(:street, id: :user_address_attributes_street) + end + end + + expected = %{
} + assert_equivalent_xml expected, output + end + end +end diff --git a/test/bootstrap_form_with_radio_button_test.rb b/test/bootstrap_form_with_radio_button_test.rb new file mode 100644 index 000000000..e30f21b33 --- /dev/null +++ b/test/bootstrap_form_with_radio_button_test.rb @@ -0,0 +1,138 @@ +if ::Rails::VERSION::STRING >= '5.1' + require 'test_helper' + + class BootstrapFormWithRadioButtonTest < ActionView::TestCase + include BootstrapForm::Helper + + def setup + setup_test_fixture + end + + test "radio_button is wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button') + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', id: :custom_id) + end + + test "radio_button disabled label is set correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', disabled: true) + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', disabled: true, id: :custom_id) + end + + test "radio_button label class is set correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', label_class: 'btn') + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', label_class: 'btn', id: :custom_id) + end + + test "radio_button inline label is set correctly" do + expected = %{} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true) + expected = %{} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true, id: :custom_id) + end + + test "radio_button disabled inline label is set correctly" do + expected = %{} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true, disabled: true) + expected = %{} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true, disabled: true, id: :custom_id) + end + + test "radio_button inline label class is set correctly" do + expected = %{} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true, label_class: 'btn') + expected = %{} + assert_equivalent_xml expected, @form_with_builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true, label_class: 'btn', id: :custom_id) + end + + # test 'collection_radio_buttons renders the form_group correctly' do + # collection = [Address.new(id: 1, street: 'Foobar')] + # expected = %{
With a help!
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, :street, label: 'This is a radio button collection', help: 'With a help!') + # end + # + # test 'collection_radio_buttons renders multiple radios correctly' do + # collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] + # puts "RAILS: #{ActionView::Helpers::FormBuilder.new(:user, @user, self, {}).collection_radio_buttons(:misc, collection, :id, :street)}" + # expected = %{
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, :street) + # end + # + # test 'collection_radio_buttons renders inline radios correctly' do + # collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] + # expected = %{
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, :street, inline: true) + # end + # + # test 'collection_radio_buttons renders with checked option correctly' do + # collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] + # expected = %{
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, :street, checked: 1) + # end + # + # test 'collection_radio_buttons renders label defined by Proc correctly' do + # collection = [Address.new(id: 1, street: 'Foobar')] + # expected = %{
With a help!
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, Proc.new { |a| a.street.reverse }, label: 'This is a radio button collection', help: 'With a help!') + # end + # + # test 'collection_radio_buttons renders value defined by Proc correctly' do + # collection = [Address.new(id: 1, street: 'Foobar')] + # expected = %{
With a help!
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, label: 'This is a radio button collection', help: 'With a help!') + # end + # + # test 'collection_radio_buttons renders multiple radios with label defined by Proc correctly' do + # collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] + # expected = %{
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, Proc.new { |a| a.street.reverse }) + # end + # + # test 'collection_radio_buttons renders multiple radios with value defined by Proc correctly' do + # collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] + # expected = %{
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street) + # end + # + # test 'collection_radio_buttons renders label defined by lambda correctly' do + # collection = [Address.new(id: 1, street: 'Foobar')] + # expected = %{
With a help!
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, lambda { |a| a.street.reverse }, label: 'This is a radio button collection', help: 'With a help!') + # end + # + # test 'collection_radio_buttons renders value defined by lambda correctly' do + # collection = [Address.new(id: 1, street: 'Foobar')] + # expected = %{
With a help!
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, label: 'This is a radio button collection', help: 'With a help!') + # end + # + # test 'collection_radio_buttons renders multiple radios with label defined by lambda correctly' do + # collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] + # expected = %{
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, :id, lambda { |a| a.street.reverse }) + # end + # + # test 'collection_radio_buttons renders multiple radios with value defined by lambda correctly' do + # collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] + # expected = %{
} + # + # assert_equivalent_xml expected, @form_with_builder.collection_radio_buttons(:misc, collection, lambda { |a| "address_#{a.id}" }, :street) + # end + end +end diff --git a/test/bootstrap_form_with_selects_test.rb b/test/bootstrap_form_with_selects_test.rb new file mode 100644 index 000000000..5bd950b3f --- /dev/null +++ b/test/bootstrap_form_with_selects_test.rb @@ -0,0 +1,211 @@ +if ::Rails::VERSION::STRING >= '5.1' + require 'test_helper' + + class BootstrapFormWithSelectsTest < ActionView::TestCase + include BootstrapForm::Helper + + def setup + setup_test_fixture + end + + # TODO: These tests reflect behaviour that might break many Capybara tests. + # TODO: Investigate whether Capybara needs the `for` attribute and the field `id` to be able to select items via their label. + + test "time zone selects are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.time_zone_select(:misc) + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.time_zone_select(:misc, nil, {}, id: "custom_id") + end + + test "selects are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]]) + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], {}, id: "custom_id") + end + + test "bootstrap_specific options are handled correctly" do + expected = %{
Help!
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], label: "My Status Label", help: "Help!" ) + expected = %{
Help!
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], { label: "My Status Label", help: "Help!" }, id: "custom_id" ) + end + + test "selects with options are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], prompt: "Please Select") + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], { prompt: "Please Select" }, id: "custom_id") + end + + test "selects with both options and html_options are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], { prompt: "Please Select" }, class: "my-select") + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], { prompt: "Please Select" }, class: "my-select", id: "custom_id") + end + + test 'selects with addons are wrapped correctly' do + expected = <<-HTML.strip_heredoc +
+ +
+ Before + + After +
+
+ HTML + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], prepend: 'Before', append: 'After') + expected = <<-HTML.strip_heredoc +
+ +
+ Before + + After +
+
+ HTML + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], { prepend: 'Before', append: 'After' }, id: "custom_id") + end + + if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("4.1.0") + test "selects with block use block as content" do + expected = %{
} + select = @form_with_builder.select(:status) do + content_tag(:option) { 'Option 1' } + + content_tag(:option) { 'Option 2' } + end + assert_equivalent_xml expected, select + expected = %{
} + select = @form_with_builder.select(:status, nil, {}, id: "custom_id") do + content_tag(:option) { 'Option 1' } + + content_tag(:option) { 'Option 2' } + end + assert_equivalent_xml expected, select + end + end + + test "selects render labels properly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], label: "User Status") + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.select(:status, [['activated', 1], ['blocked', 2]], { label: "User Status" }, id: :custom_id) + end + + test "collection_selects are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.collection_select(:status, [], :id, :name) + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.collection_select(:status, [], :id, :name, {}, id: :custom_id) + end + + test "collection_selects with options are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.collection_select(:status, [], :id, :name, prompt: "Please Select") + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.collection_select(:status, [], :id, :name, { prompt: "Please Select" }, id: :custom_id) + end + + test "collection_selects with options and html_options are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.collection_select(:status, [], :id, :name, { prompt: "Please Select" }, class: "my-select") + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.collection_select(:status, [], :id, :name, { prompt: "Please Select" }, class: "my-select", id: :custom_id) + end + + test "grouped_collection_selects are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s) + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s, {}, id: :custom_id) + end + + test "grouped_collection_selects with options are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s, prompt: "Please Select") + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s, { prompt: "Please Select" }, id: :custom_id) + end + + test "grouped_collection_selects with options and html_options are wrapped correctly" do + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s, { prompt: "Please Select" }, class: "my-select") + expected = %{
} + assert_equivalent_xml expected, @form_with_builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s, { prompt: "Please Select" }, class: "my-select", id: :custom_id) + end + + # The date and time helpers produce multiple selects. A single custom id isn't convenient. + # The Rails helpers appear to generate default IDs even under `form_with`. + # test "date selects are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3)) do + # expected = %{
\n\n\n
} + # assert_equivalent_xml expected, @form_with_builder.date_select(:misc) + # end + # end + # + # test "date selects with options are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3)) do + # expected = %{
\n\n\n
} + # assert_equivalent_xml expected, @form_with_builder.date_select(:misc, include_blank: true) + # end + # end + # + # test "date selects with options and html_options are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3)) do + # expected = %{
\n\n\n
} + # assert_equivalent_xml expected, @form_with_builder.date_select(:misc, { include_blank: true }, class: "my-date-select") + # end + # end + # + # test "time selects are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do + # expected = %{
\n\n\n\n : \n
} + # assert_equivalent_xml expected, @form_with_builder.time_select(:misc) + # end + # end + # + # test "time selects with options are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do + # expected = %{
\n\n\n\n : \n
} + # assert_equivalent_xml expected, @form_with_builder.time_select(:misc, include_blank: true) + # end + # end + # + # test "time selects with options and html_options are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do + # expected = %{
\n\n\n\n : \n
} + # assert_equivalent_xml expected, @form_with_builder.time_select(:misc, { include_blank: true }, class: "my-time-select") + # end + # end + # + # test "datetime selects are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do + # expected = %{
\n\n\n — \n : \n
} + # assert_equivalent_xml expected, @form_with_builder.datetime_select(:misc) + # end + # end + # + # test "datetime selects with options are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do + # expected = %{
\n\n\n — \n : \n
} + # assert_equivalent_xml expected, @form_with_builder.datetime_select(:misc, include_blank: true) + # end + # end + # + # test "datetime selects with options and html_options are wrapped correctly" do + # Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do + # expected = %{
\n\n\n — \n : \n
} + # assert_equivalent_xml expected, @form_with_builder.datetime_select(:misc, { include_blank: true }, class: "my-datetime-select") + # end + # end + end +end diff --git a/test/bootstrap_form_with_test.rb b/test/bootstrap_form_with_test.rb new file mode 100644 index 000000000..55095f770 --- /dev/null +++ b/test/bootstrap_form_with_test.rb @@ -0,0 +1,223 @@ +# Tests for `form_with`. +# Do all the tests for `bootstrap_form_for` and `bootstrap_form_tag`, but with +# `bootstrap_form_with`. +if ::Rails::VERSION::STRING >= '5.1' + require 'test_helper' + + class BootstrapFormWithTest < ActionView::TestCase + include BootstrapForm::Helper + + def setup + setup_test_fixture + end + + # This set of tests simply mirrors the tests in `bootstrap_form_test.rb`, but using `form_with` + # instead of `form_for` or `form_tag`. + test "form_with default-style forms" do + # https://m.patrikonrails.com/rails-5-1s-form-with-vs-old-form-helpers-3a5f72a8c78a confirms + # the `form_with` doesn't add the class and id like `form_for` did. + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user) { |f| nil } + end + + test "form_with inline-style forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :inline) { |f| nil } + end + + test "form_with horizontal-style forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal) { |f| f.email_field :email } + end + + test "form_with existing styles aren't clobbered when specifying a form style" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal, html: { class: "my-style" }) { |f| f.email_field :email } + end + + test "form_with given role attribute should not be covered by default role attribute" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, html: { role: 'not-a-form'}) {|f| nil} + end + + test "form_with bootstrap_form_tag acts like a form tag" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(url: '/users') { |f| f.text_field :email, label: "Your Email" } + end + + test "form_with bootstrap_form_tag does not clobber custom options" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(url: '/users') { |f| f.text_field :email, name: 'NAME', id: "ID" } + end + + test "form_with bootstrap_form_tag allows an empty name for checkboxes" do + checkbox = %{
} + expected = %{
#{checkbox}
} + assert_equivalent_xml expected, bootstrap_form_with(url: '/users') { |f| f.check_box :misc } + end + + test "form_with errors display correctly and inline_errors are turned off by default when label_errors is true" do + @user.email = nil + @user.valid? + + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, label_errors: true) { |f| f.text_field :email } + end + + test "form_with errors display correctly and inline_errors can also be on when label_errors is true" do + @user.email = nil + @user.valid? + + expected = %{
can't be blank, is too short (minimum is 5 characters)
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, label_errors: true, inline_errors: true) { |f| f.text_field :email } + end + + test "form_with label error messages use humanized attribute names" do + I18n.backend.store_translations(:en, {activerecord: {attributes: {user: {email: 'Your e-mail address'}}}}) + + @user.email = nil + @user.valid? + + # FIXME: This expected string isn't right. Why does it have id and for and still pass? + expected = %{
can't be blank, is too short (minimum is 5 characters)
} + assert_equivalent_xml expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| f.text_field :email } + + I18n.backend.store_translations(:en, {activerecord: {attributes: {user: {email: nil}}}}) + end + + test "form_with alert message is wrapped correctly" do + @user.email = nil + @user.valid? + expected = %{

Please fix the following errors:

  • Email can't be blank
  • Email is too short (minimum is 5 characters)
  • Terms must be accepted
} + assert_equivalent_xml expected, @builder.alert_message('Please fix the following errors:') + end + + test "form_with changing the class name for the alert message" do + @user.email = nil + @user.valid? + expected = %{

Please fix the following errors:

  • Email can't be blank
  • Email is too short (minimum is 5 characters)
  • Terms must be accepted
} + assert_equivalent_xml expected, @builder.alert_message('Please fix the following errors:', class: 'my-css-class') + end + + test "form_with alert_message contains the error summary when inline_errors are turned off" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: false) do |f| + f.alert_message('Please fix the following errors:') + end + + expected = %{

Please fix the following errors:

  • Email can't be blank
  • Email is too short (minimum is 5 characters)
  • Terms must be accepted
} + assert_equivalent_xml expected, output + end + + test "form_with alert_message allows the error_summary to be turned off" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: false) do |f| + f.alert_message('Please fix the following errors:', error_summary: false) + end + + expected = %{

Please fix the following errors:

} + assert_equivalent_xml expected, output + end + + test "form_with alert_message allows the error_summary to be turned on with inline_errors also turned on" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: true) do |f| + f.alert_message('Please fix the following errors:', error_summary: true) + end + + expected = %{

Please fix the following errors:

  • Email can't be blank
  • Email is too short (minimum is 5 characters)
  • Terms must be accepted
} + assert_equivalent_xml expected, output + end + + test "form_with error_summary returns an unordered list of errors" do + @user.email = nil + @user.valid? + + expected = %{
  • Email can't be blank
  • Email is too short (minimum is 5 characters)
  • Terms must be accepted
} + assert_equivalent_xml expected, @builder.error_summary + end + + test 'errors_on renders the errors for a specific attribute when invalid' do + @user.email = nil + @user.valid? + + expected = %{
Email can't be blank, Email is too short (minimum is 5 characters)
} + assert_equivalent_xml expected, @builder.errors_on(:email) + end + + test "form_with custom label width for horizontal forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal) { |f| f.email_field :email, label_col: 'col-sm-1' } + end + + test "form_with offset for form group without label respects label width for horizontal forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal, label_col: 'col-md-2', control_col: 'col-md-10') { |f| f.form_group { f.submit } } + end + + test "form_with custom input width for horizontal forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal) { |f| f.email_field :email, control_col: 'col-sm-5' } + end + + test "form_with the field contains the error and is not wrapped in div.field_with_errors when bootstrap_form_for is used" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user) do |f| + f.text_field(:email, help: 'This is required') + end + + expected = %{
} + assert_equivalent_xml expected, output + end + + test "form_with the field is wrapped with div.field_with_errors when form_with is used" do + @user.email = nil + @user.valid? + + # Simulate how the builder would be called from `form_with`. + output = form_with(model: @user, builder: BootstrapForm::FormBuilder, skip_default_ids: true) do |f| + f.text_field(:email, help: 'This is required') + end + + expected = %{
} + assert_equivalent_xml expected, output + end + + test "form_with help is preserved when inline_errors: false is passed to bootstrap_form_for" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: false) do |f| + f.text_field(:email, help: 'This is required') + end + + expected = %{
This is required
} + assert_equivalent_xml expected, output + end + + test "form_with allows the form object to be nil" do + # Simulate how the builder would be called from `form_with`. + builder = BootstrapForm::FormBuilder.new :other_model, nil, self, { skip_default_ids: true } + expected = %{
} + assert_equivalent_xml expected, builder.text_field(:email) + end + + test 'errors_on hide attribute name in message' do + @user.email = nil + @user.valid? + + expected = %{
can't be blank, is too short (minimum is 5 characters)
} + + assert_equivalent_xml expected, @builder.errors_on(:email, hide_attribute_name: true) + end + # End of the tests that mirror `bootstrap_form_test`. + end +end diff --git a/test/bootstrap_other_components_test.rb b/test/bootstrap_other_components_test.rb index f175c94ed..0933c56f2 100644 --- a/test/bootstrap_other_components_test.rb +++ b/test/bootstrap_other_components_test.rb @@ -10,7 +10,7 @@ def setup test "static control" do output = @horizontal_builder.static_control :email - expected = %{

steve@example.com

} + expected = %{

steve@example.com

} assert_equivalent_xml expected, output end @@ -19,7 +19,7 @@ def setup "this is a test" end - expected = %{

this is a test

} + expected = %{

this is a test

} assert_equivalent_xml expected, output end @@ -28,7 +28,7 @@ def setup "Custom Control" end - expected = %{

Custom Control

} + expected = %{

Custom Control

} assert_equivalent_xml expected, output end @@ -37,8 +37,8 @@ def setup "this is a test" end - expected = %{
this is a test
} - assert_equal expected, output + expected = %{
this is a test
} + assert_equivalent_xml expected, output end test "custom control doesn't require an actual attribute" do @@ -46,8 +46,8 @@ def setup "this is a test" end - expected = %{
this is a test
} - assert_equal expected, output + expected = %{
this is a test
} + assert_equivalent_xml expected, output end test "custom control doesn't require a name" do @@ -55,17 +55,17 @@ def setup "Custom Control" end - expected = %{
Custom Control
} - assert_equal expected, output + expected = %{
Custom Control
} + assert_equivalent_xml expected, output end test "submit button defaults to rails action name" do - expected = %{} + expected = %{} assert_equivalent_xml expected, @builder.submit end test "submit button uses default button classes" do - expected = %{} + expected = %{} assert_equivalent_xml expected, @builder.submit("Submit Form") end diff --git a/test/bootstrap_radio_button_test.rb b/test/bootstrap_radio_button_test.rb index b420c1e01..2ba720da1 100644 --- a/test/bootstrap_radio_button_test.rb +++ b/test/bootstrap_radio_button_test.rb @@ -39,84 +39,84 @@ def setup test 'collection_radio_buttons renders the form_group correctly' do collection = [Address.new(id: 1, street: 'Foobar')] - expected = %{
With a help!
} + expected = %{
With a help!
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, :street, label: 'This is a radio button collection', help: 'With a help!') end test 'collection_radio_buttons renders multiple radios correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, :street) end test 'collection_radio_buttons renders inline radios correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, :street, inline: true) end test 'collection_radio_buttons renders with checked option correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, :street, checked: 1) end test 'collection_radio_buttons renders label defined by Proc correctly' do collection = [Address.new(id: 1, street: 'Foobar')] - expected = %{
With a help!
} + expected = %{
With a help!
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, Proc.new { |a| a.street.reverse }, label: 'This is a radio button collection', help: 'With a help!') end test 'collection_radio_buttons renders value defined by Proc correctly' do collection = [Address.new(id: 1, street: 'Foobar')] - expected = %{
With a help!
} + expected = %{
With a help!
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street, label: 'This is a radio button collection', help: 'With a help!') end test 'collection_radio_buttons renders multiple radios with label defined by Proc correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, Proc.new { |a| a.street.reverse }) end test 'collection_radio_buttons renders multiple radios with value defined by Proc correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, Proc.new { |a| "address_#{a.id}" }, :street) end test 'collection_radio_buttons renders label defined by lambda correctly' do collection = [Address.new(id: 1, street: 'Foobar')] - expected = %{
With a help!
} + expected = %{
With a help!
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, lambda { |a| a.street.reverse }, label: 'This is a radio button collection', help: 'With a help!') end test 'collection_radio_buttons renders value defined by lambda correctly' do collection = [Address.new(id: 1, street: 'Foobar')] - expected = %{
With a help!
} + expected = %{
With a help!
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, lambda { |a| "address_#{a.id}" }, :street, label: 'This is a radio button collection', help: 'With a help!') end test 'collection_radio_buttons renders multiple radios with label defined by lambda correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, :id, lambda { |a| a.street.reverse }) end test 'collection_radio_buttons renders multiple radios with value defined by lambda correctly' do collection = [Address.new(id: 1, street: 'Foo'), Address.new(id: 2, street: 'Bar')] - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_radio_buttons(:misc, collection, lambda { |a| "address_#{a.id}" }, :street) end diff --git a/test/bootstrap_selects_test.rb b/test/bootstrap_selects_test.rb index 872dfb46e..f934fdd4b 100644 --- a/test/bootstrap_selects_test.rb +++ b/test/bootstrap_selects_test.rb @@ -8,34 +8,34 @@ def setup end test "time zone selects are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.time_zone_select(:misc) end test "selects are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.select(:status, [['activated', 1], ['blocked', 2]]) end test "bootstrap_specific options are handled correctly" do - expected = %{
Help!
} + expected = %{
Help!
} assert_equivalent_xml expected, @builder.select(:status, [['activated', 1], ['blocked', 2]], label: "My Status Label", help: "Help!" ) end test "selects with options are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.select(:status, [['activated', 1], ['blocked', 2]], prompt: "Please Select") end test "selects with both options and html_options are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.select(:status, [['activated', 1], ['blocked', 2]], { prompt: "Please Select" }, class: "my-select") end test 'selects with addons are wrapped correctly' do expected = <<-HTML.strip_heredoc
- +
Before
} + expected = %{
} select = @builder.select(:status) do content_tag(:option) { 'Option 1' } + content_tag(:option) { 'Option 2' } @@ -61,99 +61,99 @@ def setup end test "selects render labels properly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.select(:status, [['activated', 1], ['blocked', 2]], label: "User Status") end test "collection_selects are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_select(:status, [], :id, :name) end test "collection_selects with options are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_select(:status, [], :id, :name, prompt: "Please Select") end test "collection_selects with options and html_options are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.collection_select(:status, [], :id, :name, { prompt: "Please Select" }, class: "my-select") end test "grouped_collection_selects are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s) end test "grouped_collection_selects with options are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s, prompt: "Please Select") end test "grouped_collection_selects with options and html_options are wrapped correctly" do - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.grouped_collection_select(:status, [], :last, :first, :to_s, :to_s, { prompt: "Please Select" }, class: "my-select") end test "date selects are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3)) do - expected = %{
\n\n\n
} + expected = %{
\n\n\n
} assert_equivalent_xml expected, @builder.date_select(:misc) end end test "date selects with options are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3)) do - expected = %{
\n\n\n
} + expected = %{
\n\n\n
} assert_equivalent_xml expected, @builder.date_select(:misc, include_blank: true) end end test "date selects with options and html_options are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3)) do - expected = %{
\n\n\n
} + expected = %{
\n\n\n
} assert_equivalent_xml expected, @builder.date_select(:misc, { include_blank: true }, class: "my-date-select") end end test "time selects are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do - expected = %{
\n\n\n\n : \n
} + expected = %{
\n\n\n\n : \n
} assert_equivalent_xml expected, @builder.time_select(:misc) end end test "time selects with options are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do - expected = %{
\n\n\n\n : \n
} + expected = %{
\n\n\n\n : \n
} assert_equivalent_xml expected, @builder.time_select(:misc, include_blank: true) end end test "time selects with options and html_options are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do - expected = %{
\n\n\n\n : \n
} + expected = %{
\n\n\n\n : \n
} assert_equivalent_xml expected, @builder.time_select(:misc, { include_blank: true }, class: "my-time-select") end end test "datetime selects are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do - expected = %{
\n\n\n — \n : \n
} + expected = %{
\n\n\n — \n : \n
} assert_equivalent_xml expected, @builder.datetime_select(:misc) end end test "datetime selects with options are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do - expected = %{
\n\n\n — \n : \n
} + expected = %{
\n\n\n — \n : \n
} assert_equivalent_xml expected, @builder.datetime_select(:misc, include_blank: true) end end test "datetime selects with options and html_options are wrapped correctly" do Timecop.freeze(Time.utc(2012, 2, 3, 12, 0, 0)) do - expected = %{
\n\n\n — \n : \n
} + expected = %{
\n\n\n — \n : \n
} assert_equivalent_xml expected, @builder.datetime_select(:misc, { include_blank: true }, class: "my-datetime-select") end end diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index a072ddbdb..3d4fd4ba0 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb @@ -18,8 +18,8 @@ t.string "city" t.string "state" t.string "zip_code" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "users", force: :cascade do |t| @@ -28,8 +28,8 @@ t.text "comments" t.string "status" t.string "misc" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "preferences" t.boolean "terms", default: false t.string "type" diff --git a/test/special_form_class_models_test.rb b/test/special_form_class_models_test.rb index 2579c9a48..cc88f836a 100644 --- a/test/special_form_class_models_test.rb +++ b/test/special_form_class_models_test.rb @@ -14,7 +14,7 @@ def user_klass.model_name @horizontal_builder = BootstrapForm::FormBuilder.new(:user, @user, self, {layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10"}) I18n.backend.store_translations(:en, {activerecord: {help: {user: {password: "A good password should be at least six characters long"}}}}) - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.date_field(:misc) end @@ -24,7 +24,7 @@ def user_klass.model_name @horizontal_builder = BootstrapForm::FormBuilder.new(:user, @user, self, {layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10"}) I18n.backend.store_translations(:en, {activerecord: {help: {user: {password: "A good password should be at least six characters long"}}}}) - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.date_field(:misc) end @@ -36,7 +36,7 @@ def user_klass.model_name @horizontal_builder = BootstrapForm::FormBuilder.new(:user, @user, self, {layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10"}) I18n.backend.store_translations(:en, {activerecord: {help: {faux_user: {password: "A good password should be at least six characters long"}}}}) - expected = %{
} + expected = %{
} assert_equivalent_xml expected, @builder.date_field(:misc) end diff --git a/test/test_helper.rb b/test/test_helper.rb index e38085c2c..91f4c89fe 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -18,6 +18,8 @@ def setup_test_fixture @user = User.new(email: 'steve@example.com', password: 'secret', comments: 'my comment') @builder = BootstrapForm::FormBuilder.new(:user, @user, self, {}) + # Simulate how the builder would be called from `form_with`. + @form_with_builder = BootstrapForm::FormBuilder.new(:user, @user, self, { skip_default_ids: true }) @horizontal_builder = BootstrapForm::FormBuilder.new(:user, @user, self, { layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10" }) I18n.backend.store_translations(:en, { activerecord: {