Skip to content

Commit

Permalink
Fix a false positive for RSpec/RepeatedSubjectCall
Browse files Browse the repository at this point in the history
Fix: #1821
  • Loading branch information
ydah committed Mar 1, 2024
1 parent a9bb3f5 commit c8b59d6
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Master (Unreleased)

- Fix a false positive for `RSpec/RepeatedSubjectCall` when `subject.method_call`. ([@ydah])

## 2.27.0 (2024-03-01)

- Add new `RSpec/IsExpectedSpecify` cop. ([@ydah])
Expand Down
6 changes: 6 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4921,6 +4921,12 @@ it do
expect { my_method }.to change { A.count }
expect { my_method }.to not_change { A.count }
end
# also good
it do
expect { subject.a }.to change { A.count }
expect { subject.b }.to not_change { A.count }
end
----
=== References
Expand Down
21 changes: 11 additions & 10 deletions lib/rubocop/cop/rspec/repeated_subject_call.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ module RSpec
# expect { my_method }.to not_change { A.count }
# end
#
# # also good
# it do
# expect { subject.a }.to change { A.count }
# expect { subject.b }.to not_change { A.count }
# end
#
class RepeatedSubjectCall < Base
include TopLevelGroup

Expand Down Expand Up @@ -64,16 +70,11 @@ def on_top_level_group(node)

private

def detect_offense(example_node, subject_node)
walker = subject_node
def detect_offense(subject_node)
subject_node.each_ancestor(:block) do |block|
break if subject_node.chained?

while walker.parent? && walker.parent != example_node.body
walker = walker.parent

if walker.block_type? && walker.method?(:expect)
add_offense(walker)
return
end
add_offense(block) if block.method?(:expect)
end
end

Expand All @@ -96,7 +97,7 @@ def detect_offenses_in_example(node, subject_names)

subject_calls(node.body, Set[*subject_names, :subject]).each do |call|
if subjects_used[call.method_name]
detect_offense(node, call)
detect_offense(call)
else
subjects_used[call.method_name] = true
end
Expand Down
11 changes: 11 additions & 0 deletions spec/rubocop/cop/rspec/repeated_subject_call_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,15 @@
end
RUBY
end

it 'registers no offenses for `subject.method_call`' do
expect_no_offenses(<<~RUBY)
RSpec.describe Foo do
it do
expect { subject.a }.to change { A.count }
expect { subject.b }.to not_change { A.count }
end
end
RUBY
end
end

0 comments on commit c8b59d6

Please sign in to comment.