From 5b71b81b1e68b93992950428842c7382207378f3 Mon Sep 17 00:00:00 2001 From: Andy Sellick Date: Wed, 11 Dec 2024 13:53:08 +0000 Subject: [PATCH] Add margin_bottom option to component wrapper helper - add a margin_bottom option, which accepts a number from the govuk-frontend spacing scale to set margin bottom on components. Slightly tricky as it overlaps onto another option - classes - but all we have to do is check the number, generate the right class based on the number, then add it to the end of the classes as they are passed out from all_attributes - create a new set of styles using the govuk-frontend responsive spacing scale to use with the new option. We previously used the govuk-frontend spacing override classes, but this has long been incorrect - those should be used only where an override is necessary to achieve a style - rewrite the component wrapper helper tests a little, firstly to make more specific so that we don't have to update every test now we default output a margin class, secondly to structure and group the tests a bit more logically for readability - update a trio of components that were broken by these changes, by removing their use of the shared helper for this same functionality and updating tests accordingly --- .../lib/_spacing.scss | 8 + .../component_wrapper_helper_options.rb | 1 + .../components/_details.html.erb | 2 - .../components/_heading.html.erb | 2 +- .../components/_hint.html.erb | 2 - docs/component-wrapper-helper.md | 3 + .../presenters/component_wrapper_helper.rb | 15 +- spec/components/details_spec.rb | 11 +- spec/components/heading_spec.rb | 9 +- spec/components/hint_spec.rb | 10 +- .../component_wrapper_helper_spec.rb | 448 ++++++++++-------- 11 files changed, 271 insertions(+), 240 deletions(-) create mode 100644 app/assets/stylesheets/govuk_publishing_components/lib/_spacing.scss diff --git a/app/assets/stylesheets/govuk_publishing_components/lib/_spacing.scss b/app/assets/stylesheets/govuk_publishing_components/lib/_spacing.scss new file mode 100644 index 0000000000..6534510a34 --- /dev/null +++ b/app/assets/stylesheets/govuk_publishing_components/lib/_spacing.scss @@ -0,0 +1,8 @@ +// styles used to provide margin in the component wrapper helper +$margins: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9; + +@each $margin in $margins { + .govuk-margin-bottom-#{$margin} { + @include govuk-responsive-margin($margin, "bottom"); + } +} diff --git a/app/models/govuk_publishing_components/component_wrapper_helper_options.rb b/app/models/govuk_publishing_components/component_wrapper_helper_options.rb index 6708116518..1222ad4e8b 100644 --- a/app/models/govuk_publishing_components/component_wrapper_helper_options.rb +++ b/app/models/govuk_publishing_components/component_wrapper_helper_options.rb @@ -8,6 +8,7 @@ def self.description - `data_attributes` - accepts a hash of data attributes - `aria` - accepts a hash of aria attributes - `classes` - accepts a space separated string of classes, these should not be used for styling and must be prefixed with `js-` +- `margin_bottom` - accepts a number from `0` to `9` (`0px` to `60px`) using the [GOV.UK Frontend spacing scale](https://design-system.service.gov.uk/styles/spacing/#the-responsive-spacing-scale) (defaults to no margin) - `role` - accepts a space separated string of roles - `lang` - accepts a language attribute value - `open` - accepts an open attribute value (true or false) diff --git a/app/views/govuk_publishing_components/components/_details.html.erb b/app/views/govuk_publishing_components/components/_details.html.erb index 10d3e3b37d..467d3402d8 100644 --- a/app/views/govuk_publishing_components/components/_details.html.erb +++ b/app/views/govuk_publishing_components/components/_details.html.erb @@ -1,7 +1,6 @@ <% add_gem_component_stylesheet("details") - shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns) open ||= nil disable_ga4 ||= false @ga4 ||= OpenStruct.new(index_section: 0) unless disable_ga4 @@ -25,7 +24,6 @@ component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns) component_helper.add_class("gem-c-details govuk-details") - component_helper.add_class(shared_helper.get_margin_bottom) component_helper.add_data_attribute({ module: "ga4-event-tracker" }) unless disable_ga4 component_helper.add_data_attribute({ ga4_event: ga4_event }) unless disable_ga4 component_helper.set_open(open) diff --git a/app/views/govuk_publishing_components/components/_heading.html.erb b/app/views/govuk_publishing_components/components/_heading.html.erb index 7db7b41e4b..8f2de65518 100644 --- a/app/views/govuk_publishing_components/components/_heading.html.erb +++ b/app/views/govuk_publishing_components/components/_heading.html.erb @@ -3,6 +3,7 @@ brand ||= false lang = local_assigns[:lang].presence + local_assigns[:margin_bottom] ||= 0 brand_helper = GovukPublishingComponents::AppHelpers::BrandHelper.new(brand) heading_helper = GovukPublishingComponents::Presenters::HeadingHelper.new(local_assigns) @@ -13,7 +14,6 @@ classes << heading_helper.classes classes << brand_helper.brand_class classes << brand_helper.border_color_class - classes << shared_helper.get_margin_bottom if [*0..9].include?(local_assigns[:margin_bottom]) component_helper.add_class(classes.join(" ")) component_helper.set_id(heading_helper.id) diff --git a/app/views/govuk_publishing_components/components/_hint.html.erb b/app/views/govuk_publishing_components/components/_hint.html.erb index ded1bbff6e..f48982a5a8 100644 --- a/app/views/govuk_publishing_components/components/_hint.html.erb +++ b/app/views/govuk_publishing_components/components/_hint.html.erb @@ -4,12 +4,10 @@ local_assigns[:id] ||= "hint-#{SecureRandom.hex(4)}" is_radio_label_hint ||= false right_to_left ||= false - shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns) component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns) component_helper.add_class("gem-c-hint govuk-hint") component_helper.add_class("govuk-radios__hint") if is_radio_label_hint - component_helper.add_class(shared_helper.get_margin_bottom) if [*0..9].include?(local_assigns[:margin_bottom]) %> <%= tag.div(**component_helper.all_attributes, dir: right_to_left ? "rtl" : nil) do %> diff --git a/docs/component-wrapper-helper.md b/docs/component-wrapper-helper.md index 79d41fbfcd..71486dc303 100644 --- a/docs/component-wrapper-helper.md +++ b/docs/component-wrapper-helper.md @@ -29,6 +29,7 @@ These options can be passed to any component that uses the component wrapper. - `data_attributes` - accepts a hash of data attributes - `aria` - accepts a hash of aria attributes - `classes` - accepts a space separated string of classes, these should not be used for styling and must be prefixed with `js-` +- `margin_bottom` - accepts a number from `0` to `9` (`0px` to `60px`) using the [GOV.UK Frontend spacing scale](https://design-system.service.gov.uk/styles/spacing/#the-responsive-spacing-scale) (defaults to no margin) - `role` - accepts a space separated string of roles - `lang` - accepts a language attribute value - `open` - accepts an open attribute value (true or false) @@ -64,6 +65,8 @@ The component wrapper includes several methods to make managing options easier, data_attributes ||= {} aria_attributes ||= {} role ||= nil + # margin_bottom will be applied by default, use this line to set a different default + local_assigns[:margin_bottom] ||= 0 component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns) component_helper.add_class("gem-c-example govuk-example") # combines the given class with any passed classes diff --git a/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb b/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb index de44958be7..9efe5a9ea6 100644 --- a/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb +++ b/lib/govuk_publishing_components/presenters/component_wrapper_helper.rb @@ -14,6 +14,7 @@ def initialize(options) check_hidden_is_valid(@options[:hidden]) if @options.include?(:hidden) check_tabindex_is_valid(@options[:tabindex]) if @options.include?(:tabindex) check_dir_is_valid(@options[:dir]) if @options.include?(:dir) + check_margin_bottom_is_valid(@options[:margin_bottom]) if @options.include?(:margin_bottom) end def all_attributes @@ -22,7 +23,10 @@ def all_attributes attributes[:id] = @options[:id] unless @options[:id].blank? attributes[:data] = @options[:data_attributes] unless @options[:data_attributes].blank? attributes[:aria] = @options[:aria] unless @options[:aria].blank? - attributes[:class] = @options[:classes] unless @options[:classes].blank? + + ((@options[:classes] ||= "") << " govuk-margin-bottom-#{@options[:margin_bottom] || 3}").strip! + attributes[:class] = @options[:classes] + attributes[:role] = @options[:role] unless @options[:role].blank? attributes[:lang] = @options[:lang] unless @options[:lang].blank? attributes[:open] = @options[:open] unless @options[:open].blank? @@ -83,6 +87,11 @@ def set_dir(dir_attribute) @options[:dir] = dir_attribute end + def set_margin_bottom(margin_bottom) + check_margin_bottom_is_valid(margin_bottom) + @options[:margin_bottom] = margin_bottom + end + private def check_id_is_valid(id) @@ -170,6 +179,10 @@ def check_tabindex_is_valid(tabindex_attribute) end end + def check_margin_bottom_is_valid(margin_bottom) + raise(ArgumentError, "margin_bottom option (#{margin_bottom}) is not recognised") unless [*0..9].include?(margin_bottom) + end + def check_dir_is_valid(dir_attribute) return if dir_attribute.nil? diff --git a/spec/components/details_spec.rb b/spec/components/details_spec.rb index 9fef7f7a5e..2f8c0b2ba7 100644 --- a/spec/components/details_spec.rb +++ b/spec/components/details_spec.rb @@ -29,7 +29,7 @@ def component_name margin_bottom: 0, ) - assert_select '.govuk-details.govuk-\!-margin-bottom-0' + assert_select ".govuk-details.govuk-margin-bottom-0" end it "applies data attributes when provided" do @@ -56,15 +56,6 @@ def component_name assert_select '.govuk-details .govuk-details__summary[aria-label="label"]' end - it "defaults to the initial bottom margin if an incorrect value is passed" do - render_component( - title: "Some title", - margin_bottom: 12, - ) - - assert_select '.govuk-details.govuk-\!-margin-bottom-3' - end - it "increments the GA4 index_section parameter when more than one component instance" do render_component(title: "first details") assert_select '.govuk-details[data-ga4-event=\'{"event_name":"select_content","type":"detail","text":"first details","section":"first details","index_section":1}\']' diff --git a/spec/components/heading_spec.rb b/spec/components/heading_spec.rb index b1caf6e752..8fdf68c86d 100644 --- a/spec/components/heading_spec.rb +++ b/spec/components/heading_spec.rb @@ -76,17 +76,12 @@ def component_name it "adds margin" do render_component(text: "Margin 7", margin_bottom: 7) - assert_select '.gem-c-heading.govuk-\!-margin-bottom-7' - end - - it "defaults to no bottom margin if an incorrect value is passed" do - render_component(text: "Margin wat", margin_bottom: 20) - assert_select "[class^='govuk-\!-margin-bottom-']", false + assert_select ".gem-c-heading.govuk-margin-bottom-7" end it "has no margin class added by default" do render_component(text: "No margin") - assert_select "[class^='govuk-\!-margin-bottom-']", false + assert_select ".gem-c-heading.govuk-margin-bottom-0" end it "adds border 1" do diff --git a/spec/components/hint_spec.rb b/spec/components/hint_spec.rb index f5fd6261df..8340040341 100644 --- a/spec/components/hint_spec.rb +++ b/spec/components/hint_spec.rb @@ -26,19 +26,13 @@ def component_name it "applies a specified bottom margin" do render_component(text: "For example, ‘QQ 12 34 56 C’.", margin_bottom: 7) - assert_select '.govuk-hint.govuk-\!-margin-bottom-7' + assert_select ".govuk-hint.govuk-margin-bottom-7" end it "applies zero bottom margin" do render_component(text: "For example, ‘QQ 12 34 56 C’.", margin_bottom: 0) - assert_select '.govuk-hint.govuk-\!-margin-bottom-0' - end - - it "does not default to the initial bottom margin if an incorrect value is passed" do - render_component(text: "For example, ‘QQ 12 34 56 C’.", margin_bottom: 12) - - assert_select '.govuk-hint.govuk-\!-margin-bottom-3', false + assert_select ".govuk-hint.govuk-margin-bottom-0" end it "accepts js classes" do diff --git a/spec/lib/govuk_publishing_components/components/component_wrapper_helper_spec.rb b/spec/lib/govuk_publishing_components/components/component_wrapper_helper_spec.rb index ea8a1c4b7d..bba8dced59 100644 --- a/spec/lib/govuk_publishing_components/components/component_wrapper_helper_spec.rb +++ b/spec/lib/govuk_publishing_components/components/component_wrapper_helper_spec.rb @@ -29,67 +29,11 @@ open: true, hidden: "", tabindex: "0", + class: "govuk-margin-bottom-3", } expect(component_helper.all_attributes).to eql(expected) end - it "accepts valid class names" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes: "gem-c-component govuk-component app-c-component brand--thing brand__thing direction-rtl") - expected = { - class: "gem-c-component govuk-component app-c-component brand--thing brand__thing direction-rtl", - } - expect(component_helper.all_attributes).to eql(expected) - end - - it "rejects invalid class names" do - classes = "js-okay not-cool-man" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes:) - }.to raise_error(ArgumentError, "Classes (#{classes}) must be prefixed with `js-`") - end - - it "rejects classes that aren't an exact match of 'direction-rtl'" do - classes = "direction-rtll" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes:) - }.to raise_error(ArgumentError, "Classes (#{classes}) must be prefixed with `js-`") - end - - it "can set an id, overriding a passed value" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(id: "original") - helper.set_id("override") - expect(helper.all_attributes[:id]).to eql("override") - end - - it "does not accept invalid ids" do - ["1dstartingwithnumber", "id with spaces", "idwith.dot", "id\nwithnewline"].each do |id| - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(id:) - }.to raise_error(ArgumentError, / contain/) - end - end - - it "does not accept invalid ids when passed" do - expect { - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(id: "valid") - helper.set_id("not. a. valid. id") - }.to raise_error(ArgumentError) - end - - it "can add a class to already passed classes" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes: "js-original") - helper.add_class("gem-c-extra") - expect(helper.all_attributes[:class]).to eql("js-original gem-c-extra") - end - - it "will error if trying to add an invalid class to already passed classes" do - classes = "gem-c-extra something-invalid" - expect { - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes: "js-original") - helper.add_class(classes) - }.to raise_error(ArgumentError, "Classes (#{classes}) must be prefixed with `js-`") - end - it "does not error if passed blank values" do component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new( id: nil, @@ -99,7 +43,7 @@ role: nil, lang: nil, ) - expect(component_helper.all_attributes).to eql({}) + expect(component_helper.all_attributes).to eql({ class: "govuk-margin-bottom-3" }) component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new( id: "", @@ -109,204 +53,290 @@ role: "", lang: "", ) - expect(component_helper.all_attributes).to eql({}) + expect(component_helper.all_attributes).to eql({ class: "govuk-margin-bottom-3" }) end - it "does not accept invalid data attributes" do - invalid_data = { module: "ok", xml_something: "notok", "XML_something": "notok", "has space": "notok", "has:colon": "notok", normal: "ok" } - error = "Data attributes (xml_something, XML_something, has space, has:colon) cannot contain capitals, spaces or colons, or start with 'xml'" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(data_attributes: invalid_data) - }.to raise_error(ArgumentError, error) + describe "classes" do + it "accepts valid class names" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes: "gem-c-component govuk-component app-c-component brand--thing brand__thing direction-rtl") + expected = { + class: "gem-c-component govuk-component app-c-component brand--thing brand__thing direction-rtl govuk-margin-bottom-3", + } + expect(component_helper.all_attributes).to eql(expected) + end - expect { - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(data_attributes: { module: "something" }) - helper.add_data_attribute(invalid_data) - }.to raise_error(ArgumentError, error) - end + it "rejects invalid class names" do + classes = "js-okay not-cool-man" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes:) + }.to raise_error(ArgumentError, "Classes (#{classes}) must be prefixed with `js-`") + end - it "can add data attributes to already passed data attributes" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(data_attributes: { module: "original-module", other: "other" }) - helper.add_data_attribute({ module: "extra-module", another: "another" }) - expect(helper.all_attributes[:data]).to eql({ module: "original-module extra-module", other: "other", another: "another" }) + it "rejects classes that aren't an exact match of 'direction-rtl'" do + classes = "direction-rtll" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes:) + }.to raise_error(ArgumentError, "Classes (#{classes}) must be prefixed with `js-`") + end end - it "can add aria attributes to already passed aria attributes" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(aria: { label: "original-label", describedby: "other" }) - helper.add_aria_attribute({ label: "extra-label", controls: "something" }) - expect(helper.all_attributes[:aria]).to eql({ label: "original-label extra-label", describedby: "other", controls: "something" }) - end + describe "setting an id" do + it "can set an id, overriding a passed value" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(id: "original") + helper.set_id("override") + expect(helper.all_attributes[:id]).to eql("override") + end - it "does not accept invalid aria attributes" do - invalid_aria = { potato: "salad", label: "something", spoon: "invalid" } - error = "Aria attribute (potato, spoon) not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(aria: invalid_aria) - }.to raise_error(ArgumentError, error) + it "does not accept invalid ids" do + ["1dstartingwithnumber", "id with spaces", "idwith.dot", "id\nwithnewline"].each do |id| + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(id:) + }.to raise_error(ArgumentError, / contain/) + end + end - expect { - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(aria: { label: "something" }) - helper.add_aria_attribute(invalid_aria) - }.to raise_error(ArgumentError, error) + it "does not accept invalid ids when passed" do + expect { + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(id: "valid") + helper.set_id("not. a. valid. id") + }.to raise_error(ArgumentError) + end end - it "does not accept an invalid role" do - error = "Role attribute (custarddoughnuts, moose) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "custarddoughnuts moose") - }.to raise_error(ArgumentError, error) + describe "classes" do + it "can add a class to already passed classes" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes: "js-original") + helper.add_class("gem-c-extra") + expect(helper.all_attributes[:class]).to eql("js-original gem-c-extra govuk-margin-bottom-3") + end - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "navigation custarddoughnuts moose") - }.to raise_error(ArgumentError, error) + it "will error if trying to add an invalid class to already passed classes" do + classes = "gem-c-extra something-invalid" + expect { + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(classes: "js-original") + helper.add_class(classes) + }.to raise_error(ArgumentError, "Classes (#{classes}) must be prefixed with `js-`") + end end - it "does not accept an invalid role when passed" do - error = "Role attribute (custarddoughnuts, moose) is not recognised" - expect { - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "navigation") - helper.add_role("custarddoughnuts moose") - }.to raise_error(ArgumentError, error) + describe "data attributes" do + it "does not accept invalid data attributes" do + invalid_data = { module: "ok", xml_something: "notok", "XML_something": "notok", "has space": "notok", "has:colon": "notok", normal: "ok" } + error = "Data attributes (xml_something, XML_something, has space, has:colon) cannot contain capitals, spaces or colons, or start with 'xml'" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(data_attributes: invalid_data) + }.to raise_error(ArgumentError, error) - expect { - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "navigation") - helper.add_role("alert custarddoughnuts moose") - }.to raise_error(ArgumentError, error) - end + expect { + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(data_attributes: { module: "something" }) + helper.add_data_attribute(invalid_data) + }.to raise_error(ArgumentError, error) + end - it "does not accept an invalid lang" do - error = "lang attribute (klingon) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(lang: "klingon") - }.to raise_error(ArgumentError, error) + it "can add data attributes to already passed data attributes" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(data_attributes: { module: "original-module", other: "other" }) + helper.add_data_attribute({ module: "extra-module", another: "another" }) + expect(helper.all_attributes[:data]).to eql({ module: "original-module extra-module", other: "other", another: "another" }) + end end - it "accepts valid open attribute value" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: true) - expected = { - open: true, - } - expect(component_helper.all_attributes).to eql(expected) - end + describe "aria attributes" do + it "can add aria attributes to already passed aria attributes" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(aria: { label: "original-label", describedby: "other" }) + helper.add_aria_attribute({ label: "extra-label", controls: "something" }) + expect(helper.all_attributes[:aria]).to eql({ label: "original-label extra-label", describedby: "other", controls: "something" }) + end - it "can set an open attribute, overriding a passed value" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: true) - helper.set_open(false) - expect(helper.all_attributes[:open]).to eql(nil) - end + it "does not accept invalid aria attributes" do + invalid_aria = { potato: "salad", label: "something", spoon: "invalid" } + error = "Aria attribute (potato, spoon) not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(aria: invalid_aria) + }.to raise_error(ArgumentError, error) - it "does not include an open attribute if the option is false" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: false) - expect(component_helper.all_attributes).to eql({}) + expect { + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(aria: { label: "something" }) + helper.add_aria_attribute(invalid_aria) + }.to raise_error(ArgumentError, error) + end end - it "does not accept an invalid open value" do - error = "open attribute (false) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: "false") - }.to raise_error(ArgumentError, error) - end + describe "roles" do + it "does not accept an invalid role" do + error = "Role attribute (custarddoughnuts, moose) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "custarddoughnuts moose") + }.to raise_error(ArgumentError, error) - it "does not accept an invalid hidden value" do - error = "hidden attribute (false) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(hidden: "false") - }.to raise_error(ArgumentError, error) - end + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "navigation custarddoughnuts moose") + }.to raise_error(ArgumentError, error) + end - it "accepts valid hidden attribute value" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(hidden: "until-found") - expected = { - hidden: "until-found", - } - expect(component_helper.all_attributes).to eql(expected) - end + it "does not accept an invalid role when passed" do + error = "Role attribute (custarddoughnuts, moose) is not recognised" + expect { + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "navigation") + helper.add_role("custarddoughnuts moose") + }.to raise_error(ArgumentError, error) - it "does not accept an invalid dir value" do - error = "dir attribute (false) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(dir: "false") - }.to raise_error(ArgumentError, error) + expect { + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(role: "navigation") + helper.add_role("alert custarddoughnuts moose") + }.to raise_error(ArgumentError, error) + end end - it "accepts valid dir attribute value" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(dir: "rtl") - expected = { - dir: "rtl", - } - expect(component_helper.all_attributes).to eql(expected) - end + describe "lang" do + it "does not accept an invalid lang" do + error = "lang attribute (klingon) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(lang: "klingon") + }.to raise_error(ArgumentError, error) + end - it "can set an dir attribute, overriding a passed value" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(dir: "rtl") - helper.set_dir("ltr") - expect(helper.all_attributes[:dir]).to eql("ltr") + it "accepts valid open attribute value" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: true) + expect(component_helper.all_attributes[:open]).to eql(true) + end end - it "can set an hidden attribute, overriding a passed value" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(hidden: "until-found") - helper.set_hidden("hidden") - expect(helper.all_attributes[:hidden]).to eql("hidden") - end + describe "open" do + it "can set an open attribute, overriding a passed value" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: true) + helper.set_open(false) + expect(helper.all_attributes[:open]).to eql(nil) + end - it "can set an tabindex attribute, overriding a passed value" do - helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: -1) - helper.set_tabindex("1") - expect(helper.all_attributes[:tabindex]).to eql("1") + it "does not include an open attribute if the option is false" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: false) + expect(component_helper.all_attributes[:open]).to eql(nil) + end + + it "does not accept an invalid open value" do + error = "open attribute (false) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(open: "false") + }.to raise_error(ArgumentError, error) + end end - describe "tabindex value regex" do - it "accepts string numbers" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "-984347284732") - expected = { - tabindex: "-984347284732", - } - expect(component_helper.all_attributes).to eql(expected) + describe "hidden" do + it "does not accept an invalid hidden value" do + error = "hidden attribute (false) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(hidden: "false") + }.to raise_error(ArgumentError, error) end - it "accepts integer numbers" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: -984_347_284_732) - expected = { - tabindex: -984_347_284_732, - } - expect(component_helper.all_attributes).to eql(expected) + it "accepts valid hidden attribute value" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(hidden: "until-found") + expect(component_helper.all_attributes[:hidden]).to eql("until-found") end - it "accepts 0" do - component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "0") - expected = { - tabindex: "0", - } - expect(component_helper.all_attributes).to eql(expected) + it "can set a hidden attribute, overriding a passed value" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(hidden: "until-found") + helper.set_hidden("hidden") + expect(helper.all_attributes[:hidden]).to eql("hidden") end + end - it "does not accept text before a number" do - error = "tabindex_attribute attribute (abc1) is not recognised" + describe "dir" do + it "does not accept an invalid dir value" do + error = "dir attribute (false) is not recognised" expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "abc1") + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(dir: "false") }.to raise_error(ArgumentError, error) end - it "does not accept text after a number" do - error = "tabindex_attribute attribute (123abc) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "123abc") - }.to raise_error(ArgumentError, error) + it "accepts valid dir attribute value" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(dir: "rtl") + expect(component_helper.all_attributes[:dir]).to eql("rtl") end - it "does not accept extra negative symbols" do - error = "tabindex_attribute attribute (--1) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "--1") - }.to raise_error(ArgumentError, error) + it "can set an dir attribute, overriding a passed value" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(dir: "rtl") + helper.set_dir("ltr") + expect(helper.all_attributes[:dir]).to eql("ltr") end + end - it "does not accept extra symbols" do - error = "tabindex_attribute attribute (-1!???) is not recognised" - expect { - GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "-1!???") - }.to raise_error(ArgumentError, error) + describe "tabindex" do + it "can set an tabindex attribute, overriding a passed value" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: -1) + helper.set_tabindex("1") + expect(helper.all_attributes[:tabindex]).to eql("1") end + + describe "tabindex value regex" do + it "accepts string numbers" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "-984347284732") + expect(component_helper.all_attributes[:tabindex]).to eql("-984347284732") + end + + it "accepts integer numbers" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: -984_347_284_732) + expect(component_helper.all_attributes[:tabindex]).to eql(-984_347_284_732) + end + + it "accepts 0" do + component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "0") + expect(component_helper.all_attributes[:tabindex]).to eql("0") + end + + it "does not accept text before a number" do + error = "tabindex_attribute attribute (abc1) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "abc1") + }.to raise_error(ArgumentError, error) + end + + it "does not accept text after a number" do + error = "tabindex_attribute attribute (123abc) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "123abc") + }.to raise_error(ArgumentError, error) + end + + it "does not accept extra negative symbols" do + error = "tabindex_attribute attribute (--1) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "--1") + }.to raise_error(ArgumentError, error) + end + + it "does not accept extra symbols" do + error = "tabindex_attribute attribute (-1!???) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(tabindex: "-1!???") + }.to raise_error(ArgumentError, error) + end + end + end + end + + describe "margins" do + it "complains about an invalid margin" do + error = "margin_bottom option (15) is not recognised" + expect { + GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(margin_bottom: 15) + }.to raise_error(ArgumentError, error) + end + + it "defaults to a known margin" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new({}) + expect(helper.all_attributes[:class]).to eql("govuk-margin-bottom-3") + end + + it "accepts a passed margin" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(margin_bottom: 5) + expect(helper.all_attributes[:class]).to eql("govuk-margin-bottom-5") + end + + it "can set a margin, overriding a passed margin" do + helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(margin_bottom: 5) + helper.set_margin_bottom(0) + expect(helper.all_attributes[:class]).to eql("govuk-margin-bottom-0") end end end