diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 11:10:13 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 11:10:13 +0000 |
commit | 0ea3fcec397b69815975647f5e2aa5fe944a8486 (patch) | |
tree | 7979381b89d26011bcf9bdc989a40fcc2f1ed4ff /spec/components | |
parent | 72123183a20411a36d607d70b12d57c484394c8e (diff) | |
download | gitlab-ce-0ea3fcec397b69815975647f5e2aa5fe944a8486.tar.gz |
Add latest changes from gitlab-org/gitlab@15-1-stable-eev15.1.0-rc42
Diffstat (limited to 'spec/components')
-rw-r--r-- | spec/components/pajamas/alert_component_spec.rb | 18 | ||||
-rw-r--r-- | spec/components/pajamas/banner_component_spec.rb | 169 | ||||
-rw-r--r-- | spec/components/pajamas/button_component_spec.rb | 273 | ||||
-rw-r--r-- | spec/components/pajamas/card_component_spec.rb | 80 | ||||
-rw-r--r-- | spec/components/pajamas/checkbox_component_spec.rb | 130 | ||||
-rw-r--r-- | spec/components/pajamas/component_spec.rb | 17 | ||||
-rw-r--r-- | spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb | 110 | ||||
-rw-r--r-- | spec/components/pajamas/concerns/checkbox_radio_options_spec.rb | 32 | ||||
-rw-r--r-- | spec/components/pajamas/radio_component_spec.rb | 126 |
9 files changed, 948 insertions, 7 deletions
diff --git a/spec/components/pajamas/alert_component_spec.rb b/spec/components/pajamas/alert_component_spec.rb index e596f07a15a..1e2845c44a8 100644 --- a/spec/components/pajamas/alert_component_spec.rb +++ b/spec/components/pajamas/alert_component_spec.rb @@ -50,10 +50,12 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do before do render_inline described_class.new( title: '_title_', - alert_class: '_alert_class_', - alert_data: { - feature_id: '_feature_id_', - dismiss_endpoint: '_dismiss_endpoint_' + alert_options: { + class: '_alert_class_', + data: { + feature_id: '_feature_id_', + dismiss_endpoint: '_dismiss_endpoint_' + } } ) end @@ -106,9 +108,11 @@ RSpec.describe Pajamas::AlertComponent, :aggregate_failures, type: :component do context 'with dismissible content' do before do render_inline described_class.new( - close_button_class: '_close_button_class_', - close_button_data: { - testid: '_close_button_testid_' + close_button_options: { + class: '_close_button_class_', + data: { + testid: '_close_button_testid_' + } } ) end diff --git a/spec/components/pajamas/banner_component_spec.rb b/spec/components/pajamas/banner_component_spec.rb new file mode 100644 index 00000000000..5969f06dbad --- /dev/null +++ b/spec/components/pajamas/banner_component_spec.rb @@ -0,0 +1,169 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::BannerComponent, type: :component do + subject do + described_class.new(**options) + end + + let(:title) { "Banner title" } + let(:content) { "Banner content"} + let(:options) { {} } + + describe 'basic usage' do + before do + render_inline(subject) do |c| + c.title { title } + content + end + end + + it 'renders its content' do + expect(rendered_component).to have_text content + end + + it 'renders its title' do + expect(rendered_component).to have_css "h1[class='gl-banner-title']", text: title + end + + it 'renders a close button' do + expect(rendered_component).to have_css "button.gl-banner-close" + end + + describe 'button_text and button_link' do + let(:options) { { button_text: 'Learn more', button_link: '/learn-more' } } + + it 'define the primary action' do + expect(rendered_component).to have_css "a.btn-confirm.gl-button[href='/learn-more']", text: 'Learn more' + end + end + + describe 'banner_options' do + let(:options) { { banner_options: { class: "baz", data: { foo: "bar" } } } } + + it 'are on the banner' do + expect(rendered_component).to have_css ".gl-banner.baz[data-foo='bar']" + end + + context 'with custom classes' do + let(:options) { { variant: :introduction, banner_options: { class: 'extra special' } } } + + it 'don\'t conflict with internal banner_classes' do + expect(rendered_component).to have_css '.extra.special.gl-banner-introduction.gl-banner' + end + end + end + + describe 'close_options' do + let(:options) { { close_options: { class: "js-foo", data: { uid: "123" } } } } + + it 'are on the close button' do + expect(rendered_component).to have_css "button.gl-banner-close.js-foo[data-uid='123']" + end + end + + describe 'embedded' do + context 'by default (false)' do + it 'keeps the banner\'s borders' do + expect(rendered_component).not_to have_css ".gl-banner.gl-border-none" + end + end + + context 'when set to true' do + let(:options) { { embedded: true } } + + it 'removes the banner\'s borders' do + expect(rendered_component).to have_css ".gl-banner.gl-border-none" + end + end + end + + describe 'variant' do + context 'by default (promotion)' do + it 'applies no variant class' do + expect(rendered_component).to have_css "[class='gl-banner']" + end + end + + context 'when set to introduction' do + let(:options) { { variant: :introduction } } + + it "applies the introduction class to the banner" do + expect(rendered_component).to have_css ".gl-banner.gl-banner-introduction" + end + + it "applies the confirm class to the close button" do + expect(rendered_component).to have_css ".gl-banner-close.btn-confirm.btn-confirm-tertiary" + end + end + + context 'when set to unknown variant' do + let(:options) { { variant: :foobar } } + + it 'ignores the unknown variant' do + expect(rendered_component).to have_css "[class='gl-banner']" + end + end + end + + describe 'illustration' do + it 'has none by default' do + expect(rendered_component).not_to have_css ".gl-banner-illustration" + end + + context 'with svg_path' do + let(:options) { { svg_path: 'logo.svg' } } + + it 'renders an image as illustration' do + expect(rendered_component).to have_css ".gl-banner-illustration img" + end + end + end + end + + context 'with illustration slot' do + before do + render_inline(subject) do |c| + c.title { title } + c.illustration { "<svg></svg>".html_safe } + content + end + end + + it 'renders the slot content as illustration' do + expect(rendered_component).to have_css ".gl-banner-illustration svg" + end + + context 'and conflicting svg_path' do + let(:options) { { svg_path: 'logo.svg' } } + + it 'uses the slot content' do + expect(rendered_component).to have_css ".gl-banner-illustration svg" + expect(rendered_component).not_to have_css ".gl-banner-illustration img" + end + end + end + + context 'with primary_action slot' do + before do + render_inline(subject) do |c| + c.title { title } + c.primary_action { "<a class='special' href='#'>Special</a>".html_safe } + content + end + end + + it 'renders the slot content as the primary action' do + expect(rendered_component).to have_css "a.special", text: 'Special' + end + + context 'and conflicting button_text and button_link' do + let(:options) { { button_text: 'Not special', button_link: '/' } } + + it 'uses the slot content' do + expect(rendered_component).to have_css "a.special[href='#']", text: 'Special' + expect(rendered_component).not_to have_css "a.btn[href='/']" + end + end + end +end diff --git a/spec/components/pajamas/button_component_spec.rb b/spec/components/pajamas/button_component_spec.rb new file mode 100644 index 00000000000..60c2a2e5a06 --- /dev/null +++ b/spec/components/pajamas/button_component_spec.rb @@ -0,0 +1,273 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::ButtonComponent, type: :component do + subject do + described_class.new(**options) + end + + let(:content) { "Button content" } + let(:options) { {} } + + describe 'basic usage' do + before do + render_inline(subject) do |c| + content + end + end + + it 'renders its content' do + expect(rendered_component).to have_text content + end + + it 'adds default styling' do + expect(rendered_component).to have_css ".btn.btn-default.btn-md.gl-button" + end + + describe 'button_options' do + let(:options) { { button_options: { id: 'baz', data: { foo: 'bar' } } } } + + it 'are added to the button' do + expect(rendered_component).to have_css ".gl-button#baz[data-foo='bar']" + end + + context 'with custom classes' do + let(:options) { { variant: :danger, category: :tertiary, button_options: { class: 'custom-class' } } } + + it 'don\'t conflict with internal button_classes' do + expect(rendered_component).to have_css '.gl-button.btn-danger.btn-danger-tertiary.custom-class' + end + end + + context 'overriding base attributes' do + let(:options) { { button_options: { type: 'submit' } } } + + it 'overrides type' do + expect(rendered_component).to have_css '[type="submit"]' + end + end + end + + describe 'button_text_classes' do + let(:options) { { button_text_classes: 'custom-text-class' } } + + it 'is added to the button text' do + expect(rendered_component).to have_css ".gl-button-text.custom-text-class" + end + end + + describe 'disabled' do + context 'by default (false)' do + it 'does not have disabled styling and behavior' do + expect(rendered_component).not_to have_css ".disabled[disabled='disabled'][aria-disabled='true']" + end + end + + context 'when set to true' do + let(:options) { { disabled: true } } + + it 'has disabled styling and behavior' do + expect(rendered_component).to have_css ".disabled[disabled='disabled'][aria-disabled='true']" + end + end + end + + describe 'loading' do + context 'by default (false)' do + it 'is not disabled' do + expect(rendered_component).not_to have_css ".disabled[disabled='disabled']" + end + + it 'does not render a spinner' do + expect(rendered_component).not_to have_css ".gl-spinner[aria-label='Loading']" + end + end + + context 'when set to true' do + let(:options) { { loading: true } } + + it 'is disabled' do + expect(rendered_component).to have_css ".disabled[disabled='disabled']" + end + + it 'renders a spinner' do + expect(rendered_component).to have_css ".gl-spinner[aria-label='Loading']" + end + end + end + + describe 'block' do + context 'by default (false)' do + it 'is inline' do + expect(rendered_component).not_to have_css ".btn-block" + end + end + + context 'when set to true' do + let(:options) { { block: true } } + + it 'is block element' do + expect(rendered_component).to have_css ".btn-block" + end + end + end + + describe 'selected' do + context 'by default (false)' do + it 'does not have selected styling and behavior' do + expect(rendered_component).not_to have_css ".selected" + end + end + + context 'when set to true' do + let(:options) { { selected: true } } + + it 'has selected styling and behavior' do + expect(rendered_component).to have_css ".selected" + end + end + end + + describe 'category & variant' do + context 'with category variants' do + where(:variant) { [:default, :confirm, :danger] } + + let(:options) { { variant: variant, category: :tertiary } } + + with_them do + it 'renders the button in correct variant && category' do + expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}") + expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}-tertiary") + end + end + end + + context 'with non-category variants' do + where(:variant) { [:dashed, :link, :reset] } + + let(:options) { { variant: variant, category: :tertiary } } + + with_them do + it 'renders the button in correct variant && category' do + expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}") + expect(rendered_component).not_to have_css(".#{described_class::VARIANT_CLASSES[variant]}-tertiary") + end + end + end + + context 'with primary category' do + where(:variant) { [:default, :confirm, :danger] } + + let(:options) { { variant: variant, category: :primary } } + + with_them do + it 'renders the button in correct variant && category' do + expect(rendered_component).to have_css(".#{described_class::VARIANT_CLASSES[variant]}") + expect(rendered_component).not_to have_css(".#{described_class::VARIANT_CLASSES[variant]}-primary") + end + end + end + end + + describe 'size' do + context 'by default (medium)' do + it 'applies medium class' do + expect(rendered_component).to have_css ".btn-md" + end + end + + context 'when set to small' do + let(:options) { { size: :small } } + + it "applies the small class to the button" do + expect(rendered_component).to have_css ".btn-sm" + end + end + end + + describe 'icon' do + it 'has none by default' do + expect(rendered_component).not_to have_css ".gl-icon" + end + + context 'with icon' do + let(:options) { { icon: 'star-o', icon_classes: 'custom-icon' } } + + it 'renders an icon with custom CSS class' do + expect(rendered_component).to have_css "svg.gl-icon.gl-button-icon.custom-icon[data-testid='star-o-icon']" + expect(rendered_component).not_to have_css ".btn-icon" + end + end + + context 'with icon only and no content' do + let(:content) { nil } + let(:options) { { icon: 'star-o' } } + + it 'adds a "btn-icon" CSS class' do + expect(rendered_component).to have_css ".btn.btn-icon" + end + end + + context 'with icon only and when loading' do + let(:content) { nil } + let(:options) { { icon: 'star-o', loading: true } } + + it 'renders only a loading icon' do + expect(rendered_component).not_to have_css "svg.gl-icon.gl-button-icon.custom-icon[data-testid='star-o-icon']" + expect(rendered_component).to have_css ".gl-spinner[aria-label='Loading']" + end + end + end + + describe 'type' do + context 'by default (without href)' do + it 'has type "button"' do + expect(rendered_component).to have_css "button[type='button']" + end + end + + context 'when set to known type' do + where(:type) { [:button, :reset, :submit] } + + let(:options) { { type: type } } + + with_them do + it 'has the correct type' do + expect(rendered_component).to have_css "button[type='#{type}']" + end + end + end + + context 'when set to unkown type' do + let(:options) { { type: :madeup } } + + it 'has type "button"' do + expect(rendered_component).to have_css "button[type='button']" + end + end + + context 'for links (with href)' do + let(:options) { { href: 'https://example.com', type: :reset } } + + it 'ignores type' do + expect(rendered_component).not_to have_css "[type]" + end + end + end + + describe 'link button' do + it 'renders a button tag with type="button" when "href" is not set' do + expect(rendered_component).to have_css "button[type='button']" + end + + context 'when "href" is provided' do + let(:options) { { href: 'https://gitlab.com', target: '_blank' } } + + it "renders a link instead of the button" do + expect(rendered_component).not_to have_css "button[type='button']" + expect(rendered_component).to have_css "a[href='https://gitlab.com'][target='_blank']" + end + end + end + end +end diff --git a/spec/components/pajamas/card_component_spec.rb b/spec/components/pajamas/card_component_spec.rb new file mode 100644 index 00000000000..65522a9023f --- /dev/null +++ b/spec/components/pajamas/card_component_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::CardComponent, :aggregate_failures, type: :component do + let(:header) { 'Card header' } + let(:body) { 'Card body' } + let(:footer) { 'Card footer' } + + context 'slots' do + before do + render_inline described_class.new do |c| + c.header { header } + c.body { body } + c.footer { footer } + end + end + + it 'renders card header' do + expect(rendered_component).to have_content(header) + end + + it 'renders card body' do + expect(rendered_component).to have_content(body) + end + + it 'renders footer' do + expect(rendered_component).to have_content(footer) + end + end + + context 'with defaults' do + before do + render_inline described_class.new + end + + it 'does not have a header or footer' do + expect(rendered_component).not_to have_selector('.gl-card-header') + expect(rendered_component).not_to have_selector('.gl-card-footer') + end + + it 'renders the card and body' do + expect(rendered_component).to have_selector('.gl-card') + expect(rendered_component).to have_selector('.gl-card-body') + end + end + + context 'with custom options' do + before do + render_inline described_class.new( + card_options: { class: '_card_class_', data: { testid: '_card_testid_' } }, + header_options: { class: '_header_class_', data: { testid: '_header_testid_' } }, + body_options: { class: '_body_class_', data: { testid: '_body_testid_' } }, + footer_options: { class: '_footer_class_', data: { testid: '_footer_testid_' } }) do |c| + c.header { header } + c.body { body } + c.footer { footer } + end + end + + it 'renders card options' do + expect(rendered_component).to have_selector('._card_class_') + expect(rendered_component).to have_selector('[data-testid="_card_testid_"]') + end + + it 'renders header options' do + expect(rendered_component).to have_selector('._header_class_') + expect(rendered_component).to have_selector('[data-testid="_header_testid_"]') + end + + it 'renders body options' do + expect(rendered_component).to have_selector('._body_class_') + expect(rendered_component).to have_selector('[data-testid="_body_testid_"]') + end + + it 'renders footer options' do + expect(rendered_component).to have_selector('._footer_class_') + expect(rendered_component).to have_selector('[data-testid="_footer_testid_"]') + end + end +end diff --git a/spec/components/pajamas/checkbox_component_spec.rb b/spec/components/pajamas/checkbox_component_spec.rb new file mode 100644 index 00000000000..b2f3a84fbfe --- /dev/null +++ b/spec/components/pajamas/checkbox_component_spec.rb @@ -0,0 +1,130 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::CheckboxComponent, :aggregate_failures, type: :component do + include FormBuilderHelpers + + let_it_be(:method) { :view_diffs_file_by_file } + let_it_be(:label) { "Show one file at a time on merge request's Changes tab" } + let_it_be(:help_text) { 'Instead of all the files changed, show only one file at a time.' } + + RSpec.shared_examples 'it renders unchecked checkbox with value of `1`' do + it 'renders unchecked checkbox with value of `1`' do + expect(rendered_component).to have_unchecked_field(label, with: '1') + end + end + + context 'with default options' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + label: label + ) + ) + end + end + + include_examples 'it renders unchecked checkbox with value of `1`' + include_examples 'it does not render help text' + + it 'renders hidden input with value of `0`' do + expect(rendered_component).to have_field('user[view_diffs_file_by_file]', type: 'hidden', with: '0') + end + end + + context 'with custom options' do + let_it_be(:checked_value) { 'yes' } + let_it_be(:unchecked_value) { 'no' } + let_it_be(:checkbox_options) { { class: 'checkbox-foo-bar', checked: true } } + let_it_be(:label_options) { { class: 'label-foo-bar' } } + + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + label: label, + help_text: help_text, + checked_value: checked_value, + unchecked_value: unchecked_value, + checkbox_options: checkbox_options, + label_options: label_options + ) + ) + end + end + + include_examples 'it renders help text' + + it 'renders checked checkbox with value of `yes`' do + expect(rendered_component).to have_checked_field(label, with: checked_value, class: checkbox_options[:class]) + end + + it 'adds CSS class to label' do + expect(rendered_component).to have_selector('label.label-foo-bar') + end + + it 'renders hidden input with value of `no`' do + expect(rendered_component).to have_field('user[view_diffs_file_by_file]', type: 'hidden', with: unchecked_value) + end + end + + context 'with `label` slot' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method + ) + ) do |c| + c.label { label } + end + end + end + + include_examples 'it renders unchecked checkbox with value of `1`' + end + + context 'with `help_text` slot' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + label: label + ) + ) do |c| + c.help_text { help_text } + end + end + end + + include_examples 'it renders unchecked checkbox with value of `1`' + include_examples 'it renders help text' + end + + context 'with `label` and `help_text` slots' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method + ) + ) do |c| + c.label { label } + c.help_text { help_text } + end + end + end + + include_examples 'it renders unchecked checkbox with value of `1`' + include_examples 'it renders help text' + end +end diff --git a/spec/components/pajamas/component_spec.rb b/spec/components/pajamas/component_spec.rb index 96f6b43bac1..7385519b468 100644 --- a/spec/components/pajamas/component_spec.rb +++ b/spec/components/pajamas/component_spec.rb @@ -23,4 +23,21 @@ RSpec.describe Pajamas::Component do expect(value).to eq('something') end end + + describe '#format_options' do + it 'merges CSS classes and additional options' do + expect( + subject.send( + :format_options, + options: { foo: 'bar', class: 'gl-display-flex gl-py-5' }, + css_classes: %w(gl-px-5 gl-mt-5), + additional_options: { baz: 'bax' } + ) + ).to match({ + foo: 'bar', + baz: 'bax', + class: ['gl-px-5', 'gl-mt-5', 'gl-display-flex gl-py-5'] + }) + end + end end diff --git a/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb b/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb new file mode 100644 index 00000000000..7a792592b3c --- /dev/null +++ b/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do + let(:form) { instance_double('ActionView::Helpers::FormBuilder') } + let(:component_class) do + Class.new do + attr_reader( + :form, + :method, + :label_argument, + :help_text_argument, + :label_options, + :input_options, + :value + ) + + def initialize( + form:, + method:, + label: nil, + help_text: nil, + label_options: {}, + radio_options: {}, + value: nil + ) + @form = form + @method = method + @label_argument = label + @help_text_argument = help_text + @label_options = label_options + @input_options = radio_options + @value = value + end + + def label_content + @label_argument + end + + def help_text_content + @help_text_argument + end + + def format_options(options:, css_classes: [], additional_options: {}) + {} + end + + include Pajamas::Concerns::CheckboxRadioLabelWithHelpText + include ActionView::Helpers::TagHelper + end + end + + let_it_be(:method) { 'username' } + let_it_be(:label_options) { { class: 'foo-bar' } } + let_it_be(:value) { 'Foo bar' } + + describe '#render_label_with_help_text' do + it 'calls `#format_options` with correct arguments' do + allow(form).to receive(:label) + + component = component_class.new(form: form, method: method, label_options: label_options, value: value) + + expect(component).to receive(:format_options).with( + options: label_options, + css_classes: ['custom-control-label'], + additional_options: { value: value } + ) + + component.render_label_with_help_text + end + + context 'when `help_text` argument is passed' do + it 'calls `form.label` with `label` and `help_text` arguments used in the block' do + component = component_class.new( + form: form, + method: method, + label: 'Label argument', + help_text: 'Help text argument' + ) + + expected_label_entry = '<span>Label argument</span><p class="help-text"' \ + ' data-testid="pajamas-component-help-text">Help text argument</p>' + + expect(form).to receive(:label).with(method, {}) do |&block| + expect(block.call).to eq(expected_label_entry) + end + + component.render_label_with_help_text + end + end + + context 'when `help_text` argument is not passed' do + it 'calls `form.label` with `label` argument used in the block' do + component = component_class.new( + form: form, + method: method, + label: 'Label argument' + ) + + expected_label_entry = '<span>Label argument</span>' + + expect(form).to receive(:label).with(method, {}) do |&block| + expect(block.call).to eq(expected_label_entry) + end + + component.render_label_with_help_text + end + end + end +end diff --git a/spec/components/pajamas/concerns/checkbox_radio_options_spec.rb b/spec/components/pajamas/concerns/checkbox_radio_options_spec.rb new file mode 100644 index 00000000000..3eb888e5f3b --- /dev/null +++ b/spec/components/pajamas/concerns/checkbox_radio_options_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::Concerns::CheckboxRadioOptions do + let(:component_class) do + Class.new do + include Pajamas::Concerns::CheckboxRadioOptions + + attr_reader(:input_options) + + def initialize(input_options: {}) + @input_options = input_options + end + + def format_options(options:, css_classes: [], additional_options: {}) + {} + end + end + end + + describe '#formatted_input_options' do + let_it_be(:input_options) { { class: 'foo-bar' } } + + it 'calls `#format_options` with correct arguments' do + component = component_class.new(input_options: input_options) + + expect(component).to receive(:format_options).with(options: input_options, css_classes: ['custom-control-input']) + + component.formatted_input_options + end + end +end diff --git a/spec/components/pajamas/radio_component_spec.rb b/spec/components/pajamas/radio_component_spec.rb new file mode 100644 index 00000000000..3885d101c7a --- /dev/null +++ b/spec/components/pajamas/radio_component_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::RadioComponent, :aggregate_failures, type: :component do + include FormBuilderHelpers + + let_it_be(:method) { :access_level } + let_it_be(:label) { "Access Level" } + let_it_be(:value) { :regular } + let_it_be(:help_text) do + 'Administrators have access to all groups, projects, and users and can manage all features in this installation' + end + + RSpec.shared_examples 'it renders unchecked radio' do + it 'renders unchecked radio' do + expect(rendered_component).to have_unchecked_field(label) + end + end + + context 'with default options' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + value: value, + label: label + ) + ) + end + end + + include_examples 'it renders unchecked radio' + include_examples 'it does not render help text' + end + + context 'with custom options' do + let_it_be(:radio_options) { { class: 'radio-foo-bar', checked: true } } + let_it_be(:label_options) { { class: 'label-foo-bar' } } + + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + value: method, + label: label, + help_text: help_text, + radio_options: radio_options, + label_options: label_options + ) + ) + end + end + + include_examples 'it renders help text' + + it 'renders checked radio' do + expect(rendered_component).to have_checked_field(label, class: radio_options[:class]) + end + + it 'adds CSS class to label' do + expect(rendered_component).to have_selector('label.label-foo-bar') + end + end + + context 'with `label` slot' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + value: value + ) + ) do |c| + c.label { label } + end + end + end + + include_examples 'it renders unchecked radio' + end + + context 'with `help_text` slot' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + value: value, + label: label + ) + ) do |c| + c.help_text { help_text } + end + end + end + + include_examples 'it renders unchecked radio' + include_examples 'it renders help text' + end + + context 'with `label` and `help_text` slots' do + before do + fake_form_for do |form| + render_inline( + described_class.new( + form: form, + method: method, + value: value + ) + ) do |c| + c.label { label } + c.help_text { help_text } + end + end + end + + include_examples 'it renders unchecked radio' + include_examples 'it renders help text' + end +end |