Skip to content

Commit 5f2641f

Browse files
authored
Merge pull request #1773 from G-Rath/assert-nil
feat: support correcting `assert_nil` and `refute_nil` to `RSpec/Rails/MinitestAssertions`
2 parents d16738c + 3686720 commit 5f2641f

File tree

5 files changed

+187
-69
lines changed

5 files changed

+187
-69
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Master (Unreleased)
44

5+
- Support correcting `assert_nil` and `refute_nil` to `RSpec/Rails/MinitestAssertions`. ([@G-Rath])
6+
57
## 2.26.1 (2024-01-05)
68

79
- Fix an error for `RSpec/SharedExamples` when using examples without argument. ([@ydah])

config/default.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,7 @@ RSpec/Rails/MinitestAssertions:
11691169
Description: Check if using Minitest matchers.
11701170
Enabled: pending
11711171
VersionAdded: '2.17'
1172+
VersionChanged: "<<next>>"
11721173
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions
11731174

11741175
RSpec/Rails/NegationBeValid:

docs/modules/ROOT/pages/cops_rspecrails.adoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ end
243243
| Yes
244244
| Yes
245245
| 2.17
246-
| -
246+
| <<next>>
247247
|===
248248

249249
Check if using Minitest matchers.
@@ -257,10 +257,16 @@ assert_equal(a, b)
257257
assert_equal a, b, "must be equal"
258258
refute_equal(a, b)
259259
260+
assert_nil a
261+
refute_nil a
262+
260263
# good
261264
expect(b).to eq(a)
262265
expect(b).to(eq(a), "must be equal")
263266
expect(b).not_to eq(a)
267+
268+
expect(a).to eq(nil)
269+
expect(a).not_to eq(nil)
264270
----
265271

266272
=== References

lib/rubocop/cop/rspec_rails/minitest_assertions.rb

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,61 @@ module Rails
1212
# assert_equal a, b, "must be equal"
1313
# refute_equal(a, b)
1414
#
15+
# assert_nil a
16+
# refute_nil a
17+
#
1518
# # good
1619
# expect(b).to eq(a)
1720
# expect(b).to(eq(a), "must be equal")
1821
# expect(b).not_to eq(a)
1922
#
23+
# expect(a).to eq(nil)
24+
# expect(a).not_to eq(nil)
25+
#
2026
class MinitestAssertions < Base
2127
extend AutoCorrector
2228

2329
MSG = 'Use `%<prefer>s`.'
24-
RESTRICT_ON_SEND = %i[assert_equal refute_equal].freeze
30+
RESTRICT_ON_SEND = %i[
31+
assert_equal
32+
refute_equal
33+
assert_nil
34+
refute_nil
35+
].freeze
2536

26-
# @!method minitest_assertion(node)
27-
def_node_matcher :minitest_assertion, <<~PATTERN
37+
# @!method minitest_equal_assertion(node)
38+
def_node_matcher :minitest_equal_assertion, <<~PATTERN
2839
(send nil? {:assert_equal :refute_equal} $_ $_ $_?)
2940
PATTERN
3041

42+
# @!method minitest_nil_assertion(node)
43+
def_node_matcher :minitest_nil_assertion, <<~PATTERN
44+
(send nil? {:assert_nil :refute_nil} $_ $_?)
45+
PATTERN
46+
3147
def on_send(node)
32-
minitest_assertion(node) do |expected, actual, failure_message|
33-
prefer = replacement(node, expected, actual,
34-
failure_message.first)
35-
add_offense(node, message: message(prefer)) do |corrector|
36-
corrector.replace(node, prefer)
37-
end
48+
minitest_equal_assertion(node) do |expected, actual, fail_message|
49+
prefer = replace_equal_assertion(node, expected, actual,
50+
fail_message.first)
51+
add_an_offense(node, prefer)
52+
end
53+
54+
minitest_nil_assertion(node) do |actual, fail_message|
55+
prefer = replace_nil_assertion(node, actual,
56+
fail_message.first)
57+
add_an_offense(node, prefer)
3858
end
3959
end
4060

4161
private
4262

43-
def replacement(node, expected, actual, failure_message)
63+
def add_an_offense(node, prefer)
64+
add_offense(node, message: message(prefer)) do |corrector|
65+
corrector.replace(node, prefer)
66+
end
67+
end
68+
69+
def replace_equal_assertion(node, expected, actual, failure_message)
4470
runner = node.method?(:assert_equal) ? 'to' : 'not_to'
4571
if failure_message.nil?
4672
"expect(#{actual.source}).#{runner} eq(#{expected.source})"
@@ -50,6 +76,16 @@ def replacement(node, expected, actual, failure_message)
5076
end
5177
end
5278

79+
def replace_nil_assertion(node, actual, failure_message)
80+
runner = node.method?(:assert_nil) ? 'to' : 'not_to'
81+
if failure_message.nil?
82+
"expect(#{actual.source}).#{runner} eq(nil)"
83+
else
84+
"expect(#{actual.source}).#{runner}(eq(nil), " \
85+
"#{failure_message.source})"
86+
end
87+
end
88+
5389
def message(prefer)
5490
format(MSG, prefer: prefer)
5591
end
Lines changed: 131 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,146 @@
11
# frozen_string_literal: true
22

33
RSpec.describe RuboCop::Cop::RSpec::Rails::MinitestAssertions do
4-
it 'registers an offense when using `assert_equal`' do
5-
expect_offense(<<~RUBY)
6-
assert_equal(a, b)
7-
^^^^^^^^^^^^^^^^^^ Use `expect(b).to eq(a)`.
8-
RUBY
9-
10-
expect_correction(<<~RUBY)
11-
expect(b).to eq(a)
12-
RUBY
13-
end
4+
context 'with equal assertions' do
5+
it 'registers an offense when using `assert_equal`' do
6+
expect_offense(<<~RUBY)
7+
assert_equal(a, b)
8+
^^^^^^^^^^^^^^^^^^ Use `expect(b).to eq(a)`.
9+
RUBY
1410

15-
it 'registers an offense when using `assert_equal` with no parentheses' do
16-
expect_offense(<<~RUBY)
17-
assert_equal a, b
18-
^^^^^^^^^^^^^^^^^ Use `expect(b).to eq(a)`.
19-
RUBY
11+
expect_correction(<<~RUBY)
12+
expect(b).to eq(a)
13+
RUBY
14+
end
2015

21-
expect_correction(<<~RUBY)
22-
expect(b).to eq(a)
23-
RUBY
24-
end
16+
it 'registers an offense when using `assert_equal` with no parentheses' do
17+
expect_offense(<<~RUBY)
18+
assert_equal a, b
19+
^^^^^^^^^^^^^^^^^ Use `expect(b).to eq(a)`.
20+
RUBY
2521

26-
it 'registers an offense when using `assert_equal` with failure message' do
27-
expect_offense(<<~RUBY)
28-
assert_equal a, b, "must be equal"
29-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(b).to(eq(a), "must be equal")`.
30-
RUBY
22+
expect_correction(<<~RUBY)
23+
expect(b).to eq(a)
24+
RUBY
25+
end
3126

32-
expect_correction(<<~RUBY)
33-
expect(b).to(eq(a), "must be equal")
34-
RUBY
35-
end
27+
it 'registers an offense when using `assert_equal` with failure message' do
28+
expect_offense(<<~RUBY)
29+
assert_equal a, b, "must be equal"
30+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(b).to(eq(a), "must be equal")`.
31+
RUBY
3632

37-
it 'registers an offense when using `assert_equal` with ' \
38-
'multi-line arguments' do
39-
expect_offense(<<~RUBY)
40-
assert_equal(a,
41-
^^^^^^^^^^^^^^^ Use `expect(b).to(eq(a), "must be equal")`.
42-
b,
43-
"must be equal")
44-
RUBY
45-
46-
expect_correction(<<~RUBY)
47-
expect(b).to(eq(a), "must be equal")
48-
RUBY
49-
end
33+
expect_correction(<<~RUBY)
34+
expect(b).to(eq(a), "must be equal")
35+
RUBY
36+
end
5037

51-
it 'registers an offense when using `refute_equal`' do
52-
expect_offense(<<~RUBY)
53-
refute_equal a, b
54-
^^^^^^^^^^^^^^^^^ Use `expect(b).not_to eq(a)`.
55-
RUBY
38+
it 'registers an offense when using `assert_equal` with ' \
39+
'multi-line arguments' do
40+
expect_offense(<<~RUBY)
41+
assert_equal(a,
42+
^^^^^^^^^^^^^^^ Use `expect(b).to(eq(a), "must be equal")`.
43+
b,
44+
"must be equal")
45+
RUBY
5646

57-
expect_correction(<<~RUBY)
58-
expect(b).not_to eq(a)
59-
RUBY
60-
end
47+
expect_correction(<<~RUBY)
48+
expect(b).to(eq(a), "must be equal")
49+
RUBY
50+
end
6151

62-
it 'does not register an offense when using `expect(b).to eq(a)`' do
63-
expect_no_offenses(<<~RUBY)
64-
expect(b).to eq(a)
65-
RUBY
52+
it 'registers an offense when using `refute_equal`' do
53+
expect_offense(<<~RUBY)
54+
refute_equal a, b
55+
^^^^^^^^^^^^^^^^^ Use `expect(b).not_to eq(a)`.
56+
RUBY
57+
58+
expect_correction(<<~RUBY)
59+
expect(b).not_to eq(a)
60+
RUBY
61+
end
62+
63+
it 'does not register an offense when using `expect(b).to eq(a)`' do
64+
expect_no_offenses(<<~RUBY)
65+
expect(b).to eq(a)
66+
RUBY
67+
end
68+
69+
it 'does not register an offense when using `expect(b).not_to eq(a)`' do
70+
expect_no_offenses(<<~RUBY)
71+
expect(b).not_to eq(a)
72+
RUBY
73+
end
6674
end
6775

68-
it 'does not register an offense when using `expect(b).not_to eq(a)`' do
69-
expect_no_offenses(<<~RUBY)
70-
expect(b).not_to eq(a)
71-
RUBY
76+
context 'with nil assertions' do
77+
it 'registers an offense when using `assert_nil`' do
78+
expect_offense(<<~RUBY)
79+
assert_nil(a)
80+
^^^^^^^^^^^^^ Use `expect(a).to eq(nil)`.
81+
RUBY
82+
83+
expect_correction(<<~RUBY)
84+
expect(a).to eq(nil)
85+
RUBY
86+
end
87+
88+
it 'registers an offense when using `assert_nil` with no parentheses' do
89+
expect_offense(<<~RUBY)
90+
assert_nil a
91+
^^^^^^^^^^^^ Use `expect(a).to eq(nil)`.
92+
RUBY
93+
94+
expect_correction(<<~RUBY)
95+
expect(a).to eq(nil)
96+
RUBY
97+
end
98+
99+
it 'registers an offense when using `assert_nil` with failure message' do
100+
expect_offense(<<~RUBY)
101+
assert_nil a, "must be nil"
102+
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `expect(a).to(eq(nil), "must be nil")`.
103+
RUBY
104+
105+
expect_correction(<<~RUBY)
106+
expect(a).to(eq(nil), "must be nil")
107+
RUBY
108+
end
109+
110+
it 'registers an offense when using `assert_nil` with ' \
111+
'multi-line arguments' do
112+
expect_offense(<<~RUBY)
113+
assert_nil(a,
114+
^^^^^^^^^^^^^ Use `expect(a).to(eq(nil), "must be nil")`.
115+
"must be nil")
116+
RUBY
117+
118+
expect_correction(<<~RUBY)
119+
expect(a).to(eq(nil), "must be nil")
120+
RUBY
121+
end
122+
123+
it 'registers an offense when using `refute_nil`' do
124+
expect_offense(<<~RUBY)
125+
refute_nil a
126+
^^^^^^^^^^^^ Use `expect(a).not_to eq(nil)`.
127+
RUBY
128+
129+
expect_correction(<<~RUBY)
130+
expect(a).not_to eq(nil)
131+
RUBY
132+
end
133+
134+
it 'does not register an offense when using `expect(a).to eq(nil)`' do
135+
expect_no_offenses(<<~RUBY)
136+
expect(a).to eq(nil)
137+
RUBY
138+
end
139+
140+
it 'does not register an offense when using `expect(a).not_to eq(nil)`' do
141+
expect_no_offenses(<<~RUBY)
142+
expect(a).not_to eq(nil)
143+
RUBY
144+
end
72145
end
73146
end

0 commit comments

Comments
 (0)