diff --git a/CHANGELOG.md b/CHANGELOG.md index 50aae56..58bc92e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Drop Ruby 2.6 support. ([@ydah]) - Add new `Capybara/RSpec/PredicateMatcher` cop. ([@ydah]) +- Add new `Capybara/ClickLinkOrButtonStyle` cop. ([@ydah]) ## 2.18.0 (2023-04-21) diff --git a/config/default.yml b/config/default.yml index 98edccb..b35ee7b 100644 --- a/config/default.yml +++ b/config/default.yml @@ -9,6 +9,16 @@ Capybara: - "**/*_steps.rb" - "**/features/step_definitions/**/*" +Capybara/ClickLinkOrButtonStyle: + Description: Checks for click button or link style. + Enabled: pending + VersionAdded: "<>" + EnforcedStyle: strict + SupportedStyles: + - strict + - click_link_or_button + Reference: https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/ClickLinkOrButtonStyle + Capybara/CurrentPathExpectation: Description: Checks that no expectations are set on Capybara's `current_path`. Enabled: true diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index 66bc952..c673799 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -2,6 +2,7 @@ === Department xref:cops_capybara.adoc[Capybara] +* xref:cops_capybara.adoc#capybaraclicklinkorbuttonstyle[Capybara/ClickLinkOrButtonStyle] * xref:cops_capybara.adoc#capybaracurrentpathexpectation[Capybara/CurrentPathExpectation] * xref:cops_capybara.adoc#capybaramatchstyle[Capybara/MatchStyle] * xref:cops_capybara.adoc#capybaranegationmatcher[Capybara/NegationMatcher] diff --git a/docs/modules/ROOT/pages/cops_capybara.adoc b/docs/modules/ROOT/pages/cops_capybara.adoc index 72ac475..12f8815 100644 --- a/docs/modules/ROOT/pages/cops_capybara.adoc +++ b/docs/modules/ROOT/pages/cops_capybara.adoc @@ -1,5 +1,61 @@ = Capybara +== Capybara/ClickLinkOrButtonStyle + +|=== +| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed + +| Pending +| Yes +| No +| <> +| - +|=== + +Checks for click button or link style. + +=== Examples + +==== EnforcedStyle: strict (default) + +[source,ruby] +---- +# bad +click_link_or_button('foo') +click_on('foo') + +# good +click_link('foo') +click_button('foo') +---- + +==== EnforcedStyle: link_or_button + +[source,ruby] +---- +# bad +click_link('foo') +click_button('foo') + +# good +click_link_or_button('foo') +click_on('foo') +---- + +=== Configurable attributes + +|=== +| Name | Default value | Configurable values + +| EnforcedStyle +| `strict` +| `strict`, `click_link_or_button` +|=== + +=== References + +* https://www.rubydoc.info/gems/rubocop-capybara/RuboCop/Cop/Capybara/ClickLinkOrButtonStyle + == Capybara/CurrentPathExpectation |=== diff --git a/lib/rubocop/cop/capybara/click_link_or_button_style.rb b/lib/rubocop/cop/capybara/click_link_or_button_style.rb new file mode 100644 index 0000000..5ac0651 --- /dev/null +++ b/lib/rubocop/cop/capybara/click_link_or_button_style.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Capybara + # Checks for click button or link style. + # + # @example EnforcedStyle: strict (default) + # # bad + # click_link_or_button('foo') + # click_on('foo') + # + # # good + # click_link('foo') + # click_button('foo') + # + # @example EnforcedStyle: link_or_button + # # bad + # click_link('foo') + # click_button('foo') + # + # # good + # click_link_or_button('foo') + # click_on('foo') + # + class ClickLinkOrButtonStyle < ::RuboCop::Cop::Base + include ConfigurableEnforcedStyle + + MSG_STRICT = + 'Use `click_link` or `click_button` instead of `%s`.' + MSG_CLICK_LINK_OR_BUTTON = + 'Use `click_link_or_button` or `click_on` instead of `%s`.' + STRICT_METHODS = %i[click_link click_button].freeze + CLICK_LINK_OR_BUTTON = %i[click_link_or_button click_on].freeze + RESTRICT_ON_SEND = (STRICT_METHODS + CLICK_LINK_OR_BUTTON).freeze + + def on_send(node) + case style + when :strict + return unless strict_method?(node) + + message = format(MSG_STRICT, method: node.method_name) + when :link_or_button + return unless link_or_button_method?(node) + + message = format(MSG_CLICK_LINK_OR_BUTTON, method: node.method_name) + end + + add_offense(node, message: message) + end + + private + + def strict_method?(node) + STRICT_METHODS.include?(node.method_name) + end + + def link_or_button_method?(node) + CLICK_LINK_OR_BUTTON.include?(node.method_name) + end + end + end + end +end diff --git a/lib/rubocop/cop/capybara_cops.rb b/lib/rubocop/cop/capybara_cops.rb index 108b3b9..04ba4de 100644 --- a/lib/rubocop/cop/capybara_cops.rb +++ b/lib/rubocop/cop/capybara_cops.rb @@ -2,6 +2,7 @@ require_relative 'capybara/rspec/predicate_matcher' +require_relative 'capybara/click_link_or_button_style' require_relative 'capybara/current_path_expectation' require_relative 'capybara/match_style' require_relative 'capybara/negation_matcher' diff --git a/spec/rubocop/cop/capybara/click_link_or_button_style_spec.rb b/spec/rubocop/cop/capybara/click_link_or_button_style_spec.rb new file mode 100644 index 0000000..158cd2c --- /dev/null +++ b/spec/rubocop/cop/capybara/click_link_or_button_style_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::Cop::Capybara::ClickLinkOrButtonStyle do + let(:cop_config) { { 'EnforcedStyle' => enforced_style } } + let(:enforced_style) { 'strict' } + + context 'when EnforcedStyle is `strict`' do + let(:enforced_style) { 'strict' } + + it 'registers an offense when using `click_link_or_button`' do + expect_offense(<<~RUBY) + click_link_or_button('foo') + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `click_link` or `click_button` instead of `click_link_or_button`. + RUBY + end + + it 'registers an offense when using `click_on`' do + expect_offense(<<~RUBY) + click_on('foo') + ^^^^^^^^^^^^^^^ Use `click_link` or `click_button` instead of `click_on`. + RUBY + end + + it 'does not register an offense when using `click_link`' do + expect_no_offenses(<<~RUBY) + click_link('foo') + RUBY + end + + it 'does not register an offense when using `click_button`' do + expect_no_offenses(<<~RUBY) + click_button('foo') + RUBY + end + end + + context 'when EnforcedStyle is `link_or_button`' do + let(:enforced_style) { 'link_or_button' } + + it 'registers an offense when using `click_link`' do + expect_offense(<<~RUBY) + click_link('foo') + ^^^^^^^^^^^^^^^^ Use `click_link_or_button` or `click_on` instead of `click_link`. + RUBY + end + + it 'registers an offense when using `click_button`' do + expect_offense(<<~RUBY) + click_button('foo') + ^^^^^^^^^^^^^^^^^^ Use `click_link_or_button` or `click_on` instead of `click_button`. + RUBY + end + + it 'does not register an offense when using `click_link_or_button`' do + expect_no_offenses(<<~RUBY) + click_link_or_button('foo') + RUBY + end + + it 'does not register an offense when using `click_on`' do + expect_no_offenses(<<~RUBY) + click_on('foo') + RUBY + end + end +end