From e94b4637bdb0e8ef134f65ab2b0a7c4a5d09837e Mon Sep 17 00:00:00 2001 From: paydaylight Date: Thu, 18 Feb 2021 22:17:37 +0600 Subject: [PATCH] Add RSpec/Rails/AvoidSetupHook cop --- CHANGELOG.md | 2 + config/default.yml | 6 +++ docs/modules/ROOT/pages/cops.adoc | 1 + docs/modules/ROOT/pages/cops_rspec/rails.adoc | 33 ++++++++++++++ .../cop/rspec/rails/avoid_setup_hook.rb | 44 +++++++++++++++++++ lib/rubocop/cop/rspec_cops.rb | 1 + .../cop/rspec/rails/avoid_setup_hook_spec.rb | 34 ++++++++++++++ 7 files changed, 121 insertions(+) create mode 100644 lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb create mode 100644 spec/rubocop/cop/rspec/rails/avoid_setup_hook_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index f5467fb98..b02064fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Add missing documentation for `single_statement_only` style of `RSpec/ImplicitSubject` cop. ([@tejasbubane][]) * Fix an exception in `DescribedClass` when accessing a constant on a variable in a spec that is nested in a namespace. ([@rrosenblum][]) * Add new `RSpec/IdenticalEqualityAssertion` cop. ([@tejasbubane][]) +* Add `RSpec/Rails/AvoidSetupHook cop. ([@paydaylight][]) ## 2.3.0 (2021-04-28) @@ -618,3 +619,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features. [@stephannv]: https://github.com/stephannv [@Tietew]: https://github.com/Tietew [@rrosenblum]: https://github.com/rrosenblum +[@paydaylight]: https://github.com/paydaylight diff --git a/config/default.yml b/config/default.yml index 9da8539cb..fe526a173 100644 --- a/config/default.yml +++ b/config/default.yml @@ -759,6 +759,12 @@ RSpec/FactoryBot/FactoryClassName: VersionChanged: '2.0' StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName +RSpec/Rails/AvoidSetupHook: + Description: Checks that tests use RSpec `before` hook over Rails `setup` method. + Enabled: pending + VersionAdded: '2.4' + StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/AvoidSetupHook + RSpec/Rails/HttpStatus: Description: Enforces use of symbolic or numeric value to describe HTTP status. Enabled: true diff --git a/docs/modules/ROOT/pages/cops.adoc b/docs/modules/ROOT/pages/cops.adoc index 610c03a03..3a28ab91f 100644 --- a/docs/modules/ROOT/pages/cops.adoc +++ b/docs/modules/ROOT/pages/cops.adoc @@ -97,6 +97,7 @@ === Department xref:cops_rspec/rails.adoc[RSpec/Rails] +* xref:cops_rspec/rails.adoc#rspecrails/avoidsetuphook[RSpec/Rails/AvoidSetupHook] * xref:cops_rspec/rails.adoc#rspecrails/httpstatus[RSpec/Rails/HttpStatus] // END_COP_LIST diff --git a/docs/modules/ROOT/pages/cops_rspec/rails.adoc b/docs/modules/ROOT/pages/cops_rspec/rails.adoc index 9ef62fe06..b782e4ca7 100644 --- a/docs/modules/ROOT/pages/cops_rspec/rails.adoc +++ b/docs/modules/ROOT/pages/cops_rspec/rails.adoc @@ -1,5 +1,38 @@ = RSpec/Rails +== RSpec/Rails/AvoidSetupHook + +|=== +| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged + +| Pending +| Yes +| Yes +| 2.4 +| - +|=== + +Checks that tests use RSpec `before` hook over Rails `setup` method. + +=== Examples + +[source,ruby] +---- +# bad +setup do + allow(foo).to receive(:bar) +end + +# good +before do + allow(foo).to receive(:bar) +end +---- + +=== References + +* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/AvoidSetupHook + == RSpec/Rails/HttpStatus |=== diff --git a/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb b/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb new file mode 100644 index 000000000..00c1abe88 --- /dev/null +++ b/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + module Rails + # Checks that tests use RSpec `before` hook over Rails `setup` method. + # + # @example + # + # # bad + # setup do + # allow(foo).to receive(:bar) + # end + # + # # good + # before do + # allow(foo).to receive(:bar) + # end + # + class AvoidSetupHook < Base + extend AutoCorrector + + MSG = 'Use `before` instead of `setup`.' + + # @!method setup_call(node) + def_node_matcher :setup_call, <<-PATTERN + (block + $(send nil? :setup) + (args) _) + PATTERN + + def on_block(node) + setup_call(node) do |setup| + add_offense(node) do |corrector| + corrector.replace setup, 'before' + end + end + end + end + end + end + end +end diff --git a/lib/rubocop/cop/rspec_cops.rb b/lib/rubocop/cop/rspec_cops.rb index 922ff591f..2263e0b9a 100644 --- a/lib/rubocop/cop/rspec_cops.rb +++ b/lib/rubocop/cop/rspec_cops.rb @@ -8,6 +8,7 @@ require_relative 'rspec/factory_bot/create_list' require_relative 'rspec/factory_bot/factory_class_name' +require_relative 'rspec/rails/avoid_setup_hook' begin require_relative 'rspec/rails/http_status' rescue LoadError diff --git a/spec/rubocop/cop/rspec/rails/avoid_setup_hook_spec.rb b/spec/rubocop/cop/rspec/rails/avoid_setup_hook_spec.rb new file mode 100644 index 000000000..01c952752 --- /dev/null +++ b/spec/rubocop/cop/rspec/rails/avoid_setup_hook_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::Cop::RSpec::Rails::AvoidSetupHook do + it 'registers an offense for `setup`' do + expect_offense(<<~RUBY) + setup do + ^^^^^^^^ Use `before` instead of `setup`. + allow(foo).to receive(:bar) + end + RUBY + + expect_correction(<<~RUBY) + before do + allow(foo).to receive(:bar) + end + RUBY + end + + it 'does not register an offense for `before`' do + expect_no_offenses(<<~RUBY) + before do + allow(foo).to receive(:bar) + end + RUBY + end + + it 'does not register an offense for an unrelated `setup` call' do + expect_no_offenses(<<~RUBY) + navigation.setup do + direction 'to infinity!' + end + RUBY + end +end