Skip to content

Commit 5120ded

Browse files
committed
Add support assert_empty, assert_not_empty and refute_empty for RSpec/Rails/MinitestAssertions
1 parent f7f3987 commit 5120ded

File tree

4 files changed

+165
-43
lines changed

4 files changed

+165
-43
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Master (Unreleased)
44

5+
- Add support for `assert_empty`, `assert_not_empty` and `refute_empty` to `RSpec/Rails/MinitestAssertions`. ([@ydah])
56
- Support correcting `assert_nil` and `refute_nil` in `RSpec/Rails/MinitestAssertions`. ([@G-Rath])
67
- Support correcting `assert_not_equal` and `assert_not_equal` in `RSpec/Rails/MinitestAssertions`. ([@G-Rath])
78
- Fix a false positive for `RSpec/ExpectActual` when used with rspec-rails routing matchers. ([@naveg])

docs/modules/ROOT/pages/cops_rspecrails.adoc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,17 +256,15 @@ Check if using Minitest matchers.
256256
assert_equal(a, b)
257257
assert_equal a, b, "must be equal"
258258
refute_equal(a, b)
259-
260259
assert_nil a
261-
refute_nil a
260+
refute_empty(b)
262261
263262
# good
264263
expect(b).to eq(a)
265264
expect(b).to(eq(a), "must be equal")
266265
expect(b).not_to eq(a)
267-
268266
expect(a).to eq(nil)
269-
expect(a).not_to eq(nil)
267+
expect(a).not_to be_empty
270268
----
271269

272270
=== References

lib/rubocop/cop/rspec_rails/minitest_assertions.rb

Lines changed: 82 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,15 @@ module Rails
1111
# assert_equal(a, b)
1212
# assert_equal a, b, "must be equal"
1313
# refute_equal(a, b)
14-
#
1514
# assert_nil a
16-
# refute_nil a
15+
# refute_empty(b)
1716
#
1817
# # good
1918
# expect(b).to eq(a)
2019
# expect(b).to(eq(a), "must be equal")
2120
# expect(b).not_to eq(a)
22-
#
2321
# expect(a).to eq(nil)
24-
# expect(a).not_to eq(nil)
22+
# expect(a).not_to be_empty
2523
#
2624
class MinitestAssertions < Base
2725
extend AutoCorrector
@@ -30,66 +28,111 @@ class MinitestAssertions < Base
3028
RESTRICT_ON_SEND = %i[
3129
assert_equal
3230
assert_not_equal
33-
refute_equal
3431
assert_nil
3532
assert_not_nil
33+
assert_empty
34+
assert_not_empty
35+
refute_equal
3636
refute_nil
37+
refute_empty
3738
].freeze
3839

39-
# @!method minitest_equal_assertion(node)
40-
def_node_matcher :minitest_equal_assertion, <<~PATTERN
40+
# @!method minitest_equal(node)
41+
def_node_matcher :minitest_equal, <<~PATTERN
4142
(send nil? {:assert_equal :assert_not_equal :refute_equal} $_ $_ $_?)
4243
PATTERN
4344

44-
# @!method minitest_nil_assertion(node)
45-
def_node_matcher :minitest_nil_assertion, <<~PATTERN
45+
# @!method minitest_nil(node)
46+
def_node_matcher :minitest_nil, <<~PATTERN
4647
(send nil? {:assert_nil :assert_not_nil :refute_nil} $_ $_?)
4748
PATTERN
4849

49-
def on_send(node)
50-
minitest_equal_assertion(node) do |expected, actual, fail_message|
51-
prefer = replace_equal_assertion(node, expected, actual,
52-
fail_message.first)
53-
add_an_offense(node, prefer)
50+
# @!method minitest_empty(node)
51+
def_node_matcher :minitest_empty, <<~PATTERN
52+
(send nil? {:assert_empty :assert_not_empty :refute_empty} $_ $_?)
53+
PATTERN
54+
55+
def on_send(node) # rubocop:disable Metrics/MethodLength
56+
minitest_equal(node) do |expected, actual, failure_message|
57+
on_assertion(node, EqualAssertion.new(expected, actual,
58+
failure_message.first))
5459
end
5560

56-
minitest_nil_assertion(node) do |actual, fail_message|
57-
prefer = replace_nil_assertion(node, actual,
58-
fail_message.first)
59-
add_an_offense(node, prefer)
61+
minitest_nil(node) do |actual, failure_message|
62+
on_assertion(node, NilAssertion.new(actual,
63+
failure_message.first))
6064
end
61-
end
6265

63-
private
66+
minitest_empty(node) do |actual, failure_message|
67+
on_assertion(node, EmptyAssertion.new(actual,
68+
failure_message.first))
69+
end
70+
end
6471

65-
def add_an_offense(node, prefer)
66-
add_offense(node, message: message(prefer)) do |corrector|
67-
corrector.replace(node, prefer)
72+
def on_assertion(node, assertion)
73+
preferred = assertion.replaced(node)
74+
add_offense(node, message: message(preferred)) do |corrector|
75+
corrector.replace(node, preferred)
6876
end
6977
end
7078

71-
def replace_equal_assertion(node, expected, actual, failure_message)
72-
runner = node.method?(:assert_equal) ? 'to' : 'not_to'
73-
if failure_message.nil?
74-
"expect(#{actual.source}).#{runner} eq(#{expected.source})"
75-
else
76-
"expect(#{actual.source}).#{runner}(eq(#{expected.source}), " \
77-
"#{failure_message.source})"
79+
def message(preferred)
80+
format(MSG, prefer: preferred)
81+
end
82+
83+
# :nodoc:
84+
class EqualAssertion
85+
def initialize(expected, actual, fail_message)
86+
@expected = expected
87+
@actual = actual
88+
@fail_message = fail_message
89+
end
90+
91+
def replaced(node)
92+
runner = node.method?(:assert_equal) ? 'to' : 'not_to'
93+
if @fail_message.nil?
94+
"expect(#{@actual.source}).#{runner} eq(#{@expected.source})"
95+
else
96+
"expect(#{@actual.source}).#{runner}(eq(#{@expected.source})," \
97+
" #{@fail_message.source})"
98+
end
7899
end
79100
end
80101

81-
def replace_nil_assertion(node, actual, failure_message)
82-
runner = node.method?(:assert_nil) ? 'to' : 'not_to'
83-
if failure_message.nil?
84-
"expect(#{actual.source}).#{runner} eq(nil)"
85-
else
86-
"expect(#{actual.source}).#{runner}(eq(nil), " \
87-
"#{failure_message.source})"
102+
# :nodoc:
103+
class NilAssertion
104+
def initialize(actual, fail_message)
105+
@actual = actual
106+
@fail_message = fail_message
107+
end
108+
109+
def replaced(node)
110+
runner = node.method?(:assert_nil) ? 'to' : 'not_to'
111+
if @fail_message.nil?
112+
"expect(#{@actual.source}).#{runner} eq(nil)"
113+
else
114+
"expect(#{@actual.source}).#{runner}(eq(nil), " \
115+
"#{@fail_message.source})"
116+
end
88117
end
89118
end
90119

91-
def message(prefer)
92-
format(MSG, prefer: prefer)
120+
# :nodoc:
121+
class EmptyAssertion
122+
def initialize(actual, fail_message)
123+
@actual = actual
124+
@fail_message = fail_message
125+
end
126+
127+
def replaced(node)
128+
runner = node.method?(:assert_empty) ? 'to' : 'not_to'
129+
if @fail_message.nil?
130+
"expect(#{@actual.source}).#{runner} be_empty"
131+
else
132+
"expect(#{@actual.source}).#{runner}(be_empty, " \
133+
"#{@fail_message.source})"
134+
end
135+
end
93136
end
94137
end
95138
end

spec/rubocop/cop/rspec_rails/minitest_assertions_spec.rb

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,85 @@
164164
expect(a).not_to eq(nil)
165165
RUBY
166166
end
167+
168+
it 'registers an offense when using `assert_empty`' do
169+
expect_offense(<<~RUBY)
170+
assert_empty(a)
171+
^^^^^^^^^^^^^^^ Use `expect(a).to be_empty`.
172+
RUBY
173+
174+
expect_correction(<<~RUBY)
175+
expect(a).to be_empty
176+
RUBY
177+
end
178+
179+
it 'registers an offense when using `assert_empty` with no parentheses' do
180+
expect_offense(<<~RUBY)
181+
assert_empty a
182+
^^^^^^^^^^^^^^ Use `expect(a).to be_empty`.
183+
RUBY
184+
185+
expect_correction(<<~RUBY)
186+
expect(a).to be_empty
187+
RUBY
188+
end
189+
190+
it 'registers an offense when using `assert_empty` with failure message' do
191+
expect_offense(<<~RUBY)
192+
assert_empty a, "must be empty"
193+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(a).to(be_empty, "must be empty")`.
194+
RUBY
195+
196+
expect_correction(<<~RUBY)
197+
expect(a).to(be_empty, "must be empty")
198+
RUBY
199+
end
200+
201+
it 'registers an offense when using `assert_empty` with ' \
202+
'multi-line arguments' do
203+
expect_offense(<<~RUBY)
204+
assert_empty(a,
205+
^^^^^^^^^^^^^^^ Use `expect(a).to(be_empty, "must be empty")`.
206+
"must be empty")
207+
RUBY
208+
209+
expect_correction(<<~RUBY)
210+
expect(a).to(be_empty, "must be empty")
211+
RUBY
212+
end
213+
214+
it 'registers an offense when using `assert_not_empty`' do
215+
expect_offense(<<~RUBY)
216+
assert_not_empty a
217+
^^^^^^^^^^^^^^^^^^ Use `expect(a).not_to be_empty`.
218+
RUBY
219+
220+
expect_correction(<<~RUBY)
221+
expect(a).not_to be_empty
222+
RUBY
223+
end
224+
225+
it 'registers an offense when using `refute_empty`' do
226+
expect_offense(<<~RUBY)
227+
refute_empty a
228+
^^^^^^^^^^^^^^ Use `expect(a).not_to be_empty`.
229+
RUBY
230+
231+
expect_correction(<<~RUBY)
232+
expect(a).not_to be_empty
233+
RUBY
234+
end
235+
236+
it 'does not register an offense when using `expect(a).to be_empty`' do
237+
expect_no_offenses(<<~RUBY)
238+
expect(a).to be_empty
239+
RUBY
240+
end
241+
242+
it 'does not register an offense when using `expect(a).not_to be_empty`' do
243+
expect_no_offenses(<<~RUBY)
244+
expect(a).not_to be_empty
245+
RUBY
246+
end
167247
end
168248
end

0 commit comments

Comments
 (0)