Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading