Skip to content

Commit 7b005c7

Browse files
committed
Teach the cop about travel_back { ... }
1 parent 4fdc87c commit 7b005c7

File tree

2 files changed

+36
-53
lines changed

2 files changed

+36
-53
lines changed

lib/rubocop/cop/rspec_rails/timecop.rb

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ module RSpecRails
1616
# rather than relying on allowing time to continue to flow.
1717
#
1818
# `Timecop.return` should be replaced with `travel_back`, when used
19-
# without a block. `travel_back` does not accept a block, so where
20-
# `return` is used with a block, it should be replaced by explicitly
21-
# calling `freeze_time` with a block, and passing the `time` to
22-
# temporarily return to.
19+
# without a block. `travel_back` accepts a block starting with Rails 6.1.
20+
# For earlier Rails, where `return` is used with a block, it should
21+
# be replaced by explicitly calling `freeze_time` with a block, and
22+
# passing the `time` to temporarily return to.
2323
#
2424
# `Timecop.travel` should be replaced by `travel` or `travel_to` when
2525
# passed a `duration` or `time`, respectively. As with `Timecop.scale`,
@@ -81,7 +81,7 @@ module RSpecRails
8181
#
8282
# # good
8383
# travel_back
84-
# travel_to(time) { assert true }
84+
# travel_back { assert true }
8585
#
8686
# # bad
8787
# Timecop.scale(factor)
@@ -158,7 +158,7 @@ def on_timecop_freeze(node, arguments)
158158

159159
def on_timecop_return(node, arguments)
160160
message =
161-
format(RETURN_MESSAGE, replacement: preferred_return_replacement)
161+
format(RETURN_MESSAGE, replacement: 'travel_back')
162162
add_offense(node, message: message) do |corrector|
163163
autocorrect_return(corrector, node, arguments)
164164
end
@@ -180,16 +180,20 @@ def autocorrect_freeze(corrector, node, arguments)
180180
end
181181

182182
def autocorrect_return(corrector, node, _arguments)
183-
return if given_block?(node)
183+
return if given_block?(node) && !supports_return_with_block?
184184

185-
corrector.replace(receiver_and_message_range(node),
186-
preferred_return_replacement)
185+
corrector.replace(receiver_and_message_range(node), 'travel_back')
187186
end
188187

189188
def given_block?(node)
190189
node.parent&.block_type? && node.parent.send_node == node
191190
end
192191

192+
# travel_back { ... } was introduced in Rails 6.1
193+
def supports_return_with_block?
194+
target_rails_version >= 6.1
195+
end
196+
193197
def receiver_and_message_range(node)
194198
node.source_range.with(end_pos: node.location.selector.end_pos)
195199
end
@@ -199,12 +203,6 @@ def preferred_freeze_replacement
199203

200204
'freeze_time'
201205
end
202-
203-
def preferred_return_replacement
204-
return 'travel_back' if target_rails_version < 6.0
205-
206-
'unfreeze_time'
207-
end
208206
end
209207
end
210208
end

spec/rubocop/cop/rspec_rails/timecop_spec.rb

Lines changed: 23 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -118,63 +118,48 @@
118118
end
119119
end
120120

121-
shared_examples 'return prefers' do |replacement|
121+
shared_examples 'return prefers' do
122122
context 'when given no block' do
123-
it "flags, and corrects to `#{replacement}`" do
123+
it 'flags, and corrects to `travel_back`' do
124124
expect_offense(<<~RUBY)
125125
Timecop.return
126-
^^^^^^^^^^^^^^ Use `#{replacement}` instead of `Timecop.return`
126+
^^^^^^^^^^^^^^ Use `travel_back` instead of `Timecop.return`
127127
RUBY
128128

129129
expect_correction(<<~RUBY)
130-
#{replacement}
130+
travel_back
131131
RUBY
132132
end
133-
134-
context 'when inside a block' do
135-
it "flags, and corrects to `#{replacement}`" do
136-
expect_offense(<<~RUBY)
137-
foo { Timecop.return }
138-
^^^^^^^^^^^^^^ Use `#{replacement}` instead of `Timecop.return`
139-
RUBY
140-
141-
expect_correction(<<~RUBY)
142-
foo { #{replacement} }
143-
RUBY
144-
end
145-
end
146133
end
134+
end
147135

148-
context 'when given a block' do
149-
it 'flags, and does not correct' do
136+
describe '.return' do
137+
context 'with Rails < 6.1', :rails60 do
138+
include_examples 'return prefers'
139+
140+
it 'flags, but does not correct return with a block' do
150141
expect_offense(<<~RUBY)
151142
Timecop.return { assert true }
152-
^^^^^^^^^^^^^^ Use `#{replacement}` instead of `Timecop.return`
143+
^^^^^^^^^^^^^^ Use `travel_back` instead of `Timecop.return`
153144
RUBY
154145

155146
expect_no_corrections
156147
end
157-
158-
context 'when inside a block' do
159-
it 'flags, and does not correct' do
160-
expect_offense(<<~RUBY)
161-
foo { Timecop.return { assert true } }
162-
^^^^^^^^^^^^^^ Use `#{replacement}` instead of `Timecop.return`
163-
RUBY
164-
165-
expect_no_corrections
166-
end
167-
end
168148
end
169-
end
170149

171-
describe '.return' do
172-
context 'when Rails < 6.0', :rails52 do
173-
include_examples 'return prefers', 'travel_back'
174-
end
150+
context 'with Rails 6.1+', :rails61 do
151+
include_examples 'return prefers'
175152

176-
context 'with Rails 6.0+', :rails60 do
177-
include_examples 'return prefers', 'unfreeze_time'
153+
it 'flags, and corrects return with a block' do
154+
expect_offense(<<~RUBY)
155+
Timecop.return { assert true }
156+
^^^^^^^^^^^^^^ Use `travel_back` instead of `Timecop.return`
157+
RUBY
158+
159+
expect_correction(<<~RUBY)
160+
travel_back { assert true }
161+
RUBY
162+
end
178163
end
179164
end
180165

0 commit comments

Comments
 (0)