Skip to content

Commit

Permalink
Fix a false negative for RSpecRails/TravelAround cop when passed as…
Browse files Browse the repository at this point in the history
… a proc to a travel method

Fixes: #49
  • Loading branch information
ydah committed Feb 14, 2025
1 parent 801dfe4 commit 3d76777
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Master (Unreleased)

- Handle unknown HTTP status codes for `RSpecRails/HttpStatus` cop. ([@viralpraxis])
- Fix a false negative for `RSpecRails/TravelAround` cop when passed as a proc to a travel method. ([@ydah])

## 2.30.0 (2024-06-12)

Expand Down
5 changes: 5 additions & 0 deletions docs/modules/ROOT/pages/cops_rspecrails.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,11 @@ around do |example|
end
end
# bad
around do |example|
freeze_time(&example)
end
# good
before { freeze_time }
----
Expand Down
51 changes: 37 additions & 14 deletions lib/rubocop/cop/rspec_rails/travel_around.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ module RSpecRails
# end
# end
#
# # bad
# around do |example|
# freeze_time(&example)
# end
#
# # good
# before { freeze_time }
#
class TravelAround < ::RuboCop::Cop::Base
extend AutoCorrector

Expand All @@ -43,6 +49,13 @@ class TravelAround < ::RuboCop::Cop::Base
)
PATTERN

# @!method extract_travel_with_block_pass(node)
def_node_search :extract_travel_with_block_pass, <<~PATTERN
$(send _ TRAVEL_METHOD_NAMES
(block_pass $lvar)
)
PATTERN

# @!method match_around_each?(node)
def_node_matcher :match_around_each?, <<~PATTERN
(block
Expand All @@ -52,29 +65,39 @@ class TravelAround < ::RuboCop::Cop::Base
PATTERN

def on_block(node)
run_node = extract_run_in_travel(node)
return unless run_node
extract_run_in_travel(node) do |run_node|
run_in_travel(node, run_node)
end
extract_travel_with_block_pass(node) do |travel_node, lvar|
travel_with_block_pass(travel_node, lvar)
end
end
alias on_numblock on_block

private

def run_in_travel(node, run_node)
around_node = extract_surrounding_around_block(run_node)
return unless around_node

add_offense(node) do |corrector|
autocorrect(corrector, node, run_node, around_node)
corrector.replace(node, node.body.source)
corrector.insert_before(around_node,
"before { #{run_node.source} }\n\n")
end
end
alias on_numblock on_block

private
def travel_with_block_pass(node, lvar)
around_node = extract_surrounding_around_block(node)
return unless around_node

def autocorrect(corrector, node, run_node, around_node)
corrector.replace(
node,
node.body.source
)
corrector.insert_before(
around_node,
"before { #{run_node.source} }\n\n"
)
add_offense(node) do |corrector|
corrector.replace(node, "#{lvar.name}.run")
corrector.insert_before(
around_node,
"before { #{node.method_name} }\n\n"
)
end
end

# @param node [RuboCop::AST::BlockNode]
Expand Down
52 changes: 52 additions & 0 deletions spec/rubocop/cop/rspec_rails/travel_around_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,35 @@
end
end

context 'with `freeze_time` with `&example` in `around`' do
it 'registers offense' do
expect_offense(<<~RUBY)
around do |example|
freeze_time(&example)
^^^^^^^^^^^^^^^^^^^^^ Prefer to travel in `before` rather than `around`.
end
RUBY

expect_correction(<<~RUBY)
before { freeze_time }
around do |example|
example.run
end
RUBY
end
end

context 'with `freeze_time` with `&example` not in `around`' do
it 'registers no offense' do
expect_no_offenses(<<~RUBY)
examples.each do |example|
freeze_time(&example)
end
RUBY
end
end

context 'with `freeze_time` in `around(:each)`' do
it 'registers offense' do
expect_offense(<<~RUBY)
Expand Down Expand Up @@ -113,6 +142,29 @@
end
end

context 'with `freeze_time` with `&example` and another node in `around`' do
it 'registers offense' do
expect_offense(<<~RUBY)
around do |example|
foo
freeze_time(&example)
^^^^^^^^^^^^^^^^^^^^^ Prefer to travel in `before` rather than `around`.
end
RUBY

expect_correction(<<~RUBY)
before { freeze_time }
around do |example|
foo
example.run
end
RUBY
end
end

context 'with `travel` in `around`' do
it 'registers offense' do
expect_offense(<<~RUBY)
Expand Down

0 comments on commit 3d76777

Please sign in to comment.