diff --git a/.simplecov b/.simplecov index d64c551..2454788 100644 --- a/.simplecov +++ b/.simplecov @@ -2,7 +2,7 @@ SimpleCov.start do enable_coverage :branch - minimum_coverage line: 99.12, branch: 90.29 + minimum_coverage line: 99.12, branch: 89.90 add_filter '/spec/' add_filter '/vendor/bundle/' end diff --git a/CHANGELOG.md b/CHANGELOG.md index e060393..59dd333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add new `Capybara/RSpec/PredicateMatcher` cop. ([@ydah]) - Fix a false positive for `Capybara/SpecificFinders` when `find` with kind option. ([@ydah]) - Add new `Capybara/RSpec/HaveSelector` 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 62467a9..a3341c6 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 + - 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 17675c4..ace8a67 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 203c08e..7ba861d 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`, `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..c8d0811 --- /dev/null +++ b/lib/rubocop/cop/capybara/click_link_or_button_style.rb @@ -0,0 +1,68 @@ +# 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) + return unless offense?(node) + + add_offense(node, message: offense_message(node)) + end + + private + + def offense?(node) + style == :strict && !strict_method?(node) || + style == :link_or_button && !link_or_button_method?(node) + end + + def offense_message(node) + if style == :strict + format(MSG_STRICT, method: node.method_name) + elsif style == :link_or_button + format(MSG_CLICK_LINK_OR_BUTTON, method: node.method_name) + end + end + + 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 dc430b1..9dd1fb7 100644 --- a/lib/rubocop/cop/capybara_cops.rb +++ b/lib/rubocop/cop/capybara_cops.rb @@ -3,6 +3,7 @@ require_relative 'capybara/rspec/have_selector' 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..9bca92c --- /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