diff --git a/CHANGELOG.md b/CHANGELOG.md index 93499ceaf..a93ca6537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Master (Unreleased) +- Fix `RSpec/VoidExpect` to only operate inside an example block. ([@corsonknowles]) + ## 3.1.0 (2024-10-01) - Add `RSpec/StringAsInstanceDoubleConstant` to check for and correct strings used as instance_doubles. ([@corsonknowles]) diff --git a/lib/rubocop/cop/rspec/void_expect.rb b/lib/rubocop/cop/rspec/void_expect.rb index 8db6a496c..52f32147c 100644 --- a/lib/rubocop/cop/rspec/void_expect.rb +++ b/lib/rubocop/cop/rspec/void_expect.rb @@ -29,12 +29,14 @@ class VoidExpect < Base def on_send(node) return unless expect?(node) + return unless inside_example?(node) check_expect(node) end def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler return unless expect_block?(node) + return unless inside_example?(node) check_expect(node) end @@ -49,11 +51,14 @@ def check_expect(node) def void?(expect) parent = expect.parent - return true unless parent return true if parent.begin_type? parent.block_type? && parent.body == expect end + + def inside_example?(node) + node.each_ancestor(:block).any? { |ancestor| example?(ancestor) } + end end end end diff --git a/spec/rubocop/cop/rspec/void_expect_spec.rb b/spec/rubocop/cop/rspec/void_expect_spec.rb index 5791d7161..1ccf3ae74 100644 --- a/spec/rubocop/cop/rspec/void_expect_spec.rb +++ b/spec/rubocop/cop/rspec/void_expect_spec.rb @@ -44,4 +44,26 @@ end RUBY end + + it 'ignores unrelated method named expect in an example block' do + expect_no_offenses(<<~RUBY) + it 'something' do + MyObject.expect(:foo) + end + RUBY + end + + context 'when expect has no parent node' do + it 'does not register an offense' do + expect_no_offenses(<<~RUBY) + expect(something) + RUBY + end + + it 'does not register an offense for unrelated expect with block' do + expect_no_offenses(<<~RUBY) + expect { block_contents } + RUBY + end + end end