diff --git a/CHANGELOG.md b/CHANGELOG.md index aa199ab0c..769f25b2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Master (Unreleased) +* Add new `RSpec/RedundantContext` cop. ([@tejasbubane]) + ## 3.3.0 (2024-12-12) - Deprecate `top_level_group?` method from `TopLevelGroup` mixin as all of its callers were intentionally removed from `Rubocop/RSpec`. ([@corsonknowles]) diff --git a/config/default.yml b/config/default.yml index 6c09b7d72..2c4e9b438 100644 --- a/config/default.yml +++ b/config/default.yml @@ -794,6 +794,12 @@ RSpec/RedundantAround: VersionAdded: '2.19' Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantAround +RSpec/RedundantContext: + Description: Remove redundant `around` hook. + Enabled: true + VersionAdded: 3.4.0 + Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RedundantContext + RSpec/RedundantPredicateMatcher: Description: Checks for redundant predicate matcher. Enabled: true diff --git a/lib/rubocop/cop/rspec/redundant_context.rb b/lib/rubocop/cop/rspec/redundant_context.rb new file mode 100644 index 000000000..77de36237 --- /dev/null +++ b/lib/rubocop/cop/rspec/redundant_context.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module RSpec + # Remove redundant `around` hook. + # + # @example + # # bad + # context 'when condition' do + # it 'tests something' do + # end + # end + # + # # good + # it 'tests something when condition' do + # end + # + class RedundantContext < Base + MSG = 'Redundant context with single example.' + + # @!method redundant_context?(node) + def_node_matcher :redundant_context?, <<~PATTERN + (block + (send #rspec? :context _) + _ + (block (send _ :it ...) ...)) + PATTERN + + def on_block(node) + return unless redundant_context?(node) + + add_offense(node) + end + alias on_numblock on_block + end + end + end +end diff --git a/lib/rubocop/cop/rspec_cops.rb b/lib/rubocop/cop/rspec_cops.rb index 85c177e8e..fa67cd921 100644 --- a/lib/rubocop/cop/rspec_cops.rb +++ b/lib/rubocop/cop/rspec_cops.rb @@ -81,6 +81,7 @@ require_relative 'rspec/receive_messages' require_relative 'rspec/receive_never' require_relative 'rspec/redundant_around' +require_relative 'rspec/redundant_context' require_relative 'rspec/redundant_predicate_matcher' require_relative 'rspec/remove_const' require_relative 'rspec/repeated_description' diff --git a/spec/rubocop/cop/rspec/redundant_context_spec.rb b/spec/rubocop/cop/rspec/redundant_context_spec.rb new file mode 100644 index 000000000..616d96dfe --- /dev/null +++ b/spec/rubocop/cop/rspec/redundant_context_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::Cop::RSpec::RedundantContext do + it 'registers an offense when single example inside context' do + expect_offense(<<~RUBY) + context 'when condition' do + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Redundant context with single example. + it 'does something' do + end + end + RUBY + end + + it 'does not register offense when multiple examples inside context' do + expect_no_offenses(<<~RUBY) + context 'when condition' do + it 'does something' do + end + + it 'does something else' do + end + end + RUBY + end +end