Skip to content

Add RSpecRails/Timecop cop #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Appease RuboCop
  • Loading branch information
pirj committed Aug 7, 2024
commit 4fdc87c5d450b1c17e9f44b87d27fb3c6684b6b2
2 changes: 1 addition & 1 deletion config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ RSpecRails/NegationBeValid:
Reference: https://www.rubydoc.info/gems/rubocop-rspec_rails/RuboCop/Cop/RSpecRails/NegationBeValid

RSpecRails/Timecop:
Description: Enforces use of `ActiveSupport::Testing::TimeHelpers` instead of `Timecop`.
Description: Enforces use of ActiveSupport TimeHelpers instead of Timecop.
Enabled: pending
VersionAdded: "<<next>>"
SafeAutoCorrect: false
Expand Down
34 changes: 24 additions & 10 deletions lib/rubocop/cop/rspec_rails/timecop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module RuboCop
module Cop
module RSpecRails
# Enforces use of `ActiveSupport::Testing::TimeHelpers` instead of `Timecop`.
# Enforces use of ActiveSupport TimeHelpers instead of Timecop.
#
# ## Migration
# `Timecop.freeze` should be replaced with `freeze_time` when used
Expand Down Expand Up @@ -96,17 +96,25 @@ class Timecop < ::RuboCop::Cop::Base
extend AutoCorrector

FREEZE_MESSAGE = 'Use `%<replacement>s` instead of `Timecop.freeze`'
FREEZE_WITH_ARGUMENTS_MESSAGE = 'Use `travel` or `travel_to` instead of `Timecop.freeze`'
FREEZE_WITH_ARGUMENTS_MESSAGE =
'Use `travel` or `travel_to` instead of `Timecop.freeze`'
RETURN_MESSAGE = 'Use `%<replacement>s` instead of `Timecop.return`'
FLOW_ADDENDUM = 'If you need time to keep flowing, simulate it by travelling again.'
TRAVEL_MESSAGE = "Use `travel` or `travel_to` instead of `Timecop.travel`. #{FLOW_ADDENDUM}"
SCALE_MESSAGE = "Use `travel` or `travel_to` instead of `Timecop.scale`. #{FLOW_ADDENDUM}"
FLOW_ADDENDUM =
'If you need time to keep flowing, simulate it by travelling again.'
TRAVEL_MESSAGE =
'Use `travel` or `travel_to` instead of `Timecop.travel`. ' \
"#{FLOW_ADDENDUM}"
SCALE_MESSAGE =
'Use `travel` or `travel_to` instead of `Timecop.scale`. ' \
"#{FLOW_ADDENDUM}"
MSG = 'Use `ActiveSupport::Testing::TimeHelpers` instead of `Timecop`'

# @!method timecop_const?(node)
def_node_matcher :timecop_const?, <<~PATTERN
(const {nil? cbase} :Timecop)
PATTERN

# @!method timecop_send(node)
def_node_matcher :timecop_send, <<~PATTERN
(send
#timecop_const? ${:freeze :return :scale :travel}
Expand Down Expand Up @@ -138,7 +146,9 @@ def on_timecop_send(node, message, arguments)

def on_timecop_freeze(node, arguments)
if arguments.empty?
add_offense(node, message: format(FREEZE_MESSAGE, replacement: preferred_freeze_replacement)) do |corrector|
message =
format(FREEZE_MESSAGE, replacement: preferred_freeze_replacement)
add_offense(node, message: message) do |corrector|
autocorrect_freeze(corrector, node, arguments)
end
else
Expand All @@ -147,7 +157,9 @@ def on_timecop_freeze(node, arguments)
end

def on_timecop_return(node, arguments)
add_offense(node, message: format(RETURN_MESSAGE, replacement: preferred_return_replacement)) do |corrector|
message =
format(RETURN_MESSAGE, replacement: preferred_return_replacement)
add_offense(node, message: message) do |corrector|
autocorrect_return(corrector, node, arguments)
end
end
Expand All @@ -163,17 +175,19 @@ def on_timecop_travel(node, _arguments)
def autocorrect_freeze(corrector, node, arguments)
return unless arguments.empty?

corrector.replace(receiver_and_message_range(node), preferred_freeze_replacement)
corrector.replace(receiver_and_message_range(node),
preferred_freeze_replacement)
end

def autocorrect_return(corrector, node, _arguments)
return if given_block?(node)

corrector.replace(receiver_and_message_range(node), preferred_return_replacement)
corrector.replace(receiver_and_message_range(node),
preferred_return_replacement)
end

def given_block?(node)
node.send_type? && node.parent && node.parent.block_type? && node.parent.send_node == node
node.parent&.block_type? && node.parent.send_node == node
end

def receiver_and_message_range(node)
Expand Down
Loading