diff --git a/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb b/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb index 13a7e34e..2eaf1631 100644 --- a/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +++ b/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb @@ -31,7 +31,7 @@ def options { id: field_id(link_errors: @link_errors), class: %(#{brand}-checkboxes__input), - aria: { describedby: [hint_id] } + aria: { describedby: hint_id } } end diff --git a/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb b/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb index f3006ebb..b6b81fcf 100644 --- a/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +++ b/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb @@ -35,7 +35,7 @@ def radio def options { id: field_id(link_errors: @link_errors), - aria: { describedby: [hint_id] }, + aria: { describedby: hint_id }, class: %(#{brand}-radios__input) } end diff --git a/lib/govuk_design_system_formbuilder/traits/html_attributes.rb b/lib/govuk_design_system_formbuilder/traits/html_attributes.rb index 7203e63e..9b3157c3 100644 --- a/lib/govuk_design_system_formbuilder/traits/html_attributes.rb +++ b/lib/govuk_design_system_formbuilder/traits/html_attributes.rb @@ -1,45 +1,50 @@ module GOVUKDesignSystemFormBuilder module Traits module HTMLAttributes - class Parser - # target any element where the content is a string that represents a - # list of things separated by a space, e.g., - # - # xyz - # - # could be respresented as - # - # = span(class: %w(red spots)) { "xyz" } - TARGETS = [%i(class), %i(aria describedby)].freeze - - def initialize(attributes) - @attributes = parse(attributes) + # Attributes eases working with default and custom attributes by + # * deeply merging them so both the default (required) attributes are + # present + # * joins the arrays into strings to maintain Rails 6.0.3 compatibility + class Attributes + def initialize(defaults, custom) + @merged = defaults.deeper_merge(deep_split_values(custom)) end def to_h - @attributes + deep_join_values(@merged) end private - def parse(attributes) - attributes.tap do |a| - a[:class] = a[:class].split if has_class_string?(a) - a[:aria][:describedby] = a[:aria][:describedby].split if has_aria_describedby_string?(attributes) + def deep_split_values(hash) + hash.each.with_object({}) do |(key, value), result| + result[key] = case value + when Hash + deep_split_values(value) + when String + value.split + else + value + end end end - def has_class_string?(attributes) - attributes.key?(:class) && attributes[:class].is_a?(String) - end - - def has_aria_describedby_string?(attributes) - attributes.dig(:aria, :describedby)&.is_a?(String) + def deep_join_values(hash) + hash.each.with_object({}) do |(key, value), result| + result[key] = case value + when Hash + deep_join_values(value) + when Array + value.uniq.join(' ').presence + else + value + end + end end end def attributes(html_attributes = {}) - options.deeper_merge(Parser.new(html_attributes).to_h) + Attributes.new(options, html_attributes).to_h end end end diff --git a/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb b/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb index 73559207..32548424 100644 --- a/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb +++ b/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb @@ -148,7 +148,7 @@ end end - specify 'radio buttons without hints shouldn not have aria-describedby attributes' do + specify 'radio buttons without hints should not have aria-describedby attributes' do colours_without_descriptions.each do |cwd| "person-favourite_colour-#{cwd.id}-hint".tap do |association| expect(subject).not_to have_tag('input', with: { "aria-describedby" => association })