@@ -26,115 +26,6 @@ module Rails
2626 class MinitestAssertions < Base
2727 extend AutoCorrector
2828
29- MSG = 'Use `%<prefer>s`.'
30- RESTRICT_ON_SEND = %i[
31- assert_equal
32- assert_not_equal
33- assert_instance_of
34- assert_not_instance_of
35- assert_includes
36- assert_not_includes
37- assert_predicate
38- assert_not_predicate
39- assert_match
40- assert_nil
41- assert_not_nil
42- assert_empty
43- assert_not_empty
44- refute_equal
45- refute_instance_of
46- refute_includes
47- refute_predicate
48- refute_nil
49- refute_empty
50- refute_match
51- ] . freeze
52-
53- # @!method minitest_equal(node)
54- def_node_matcher :minitest_equal , <<~PATTERN
55- (send nil? {:assert_equal :assert_not_equal :refute_equal} $_ $_ $_?)
56- PATTERN
57-
58- # @!method minitest_instance_of(node)
59- def_node_matcher :minitest_instance_of , <<~PATTERN
60- (send nil? {:assert_instance_of :assert_not_instance_of :refute_instance_of} $_ $_ $_?)
61- PATTERN
62-
63- # @!method minitest_includes(node)
64- def_node_matcher :minitest_includes , <<~PATTERN
65- (send nil? {:assert_includes :assert_not_includes :refute_includes} $_ $_ $_?)
66- PATTERN
67-
68- # @!method minitest_predicate(node)
69- def_node_matcher :minitest_predicate , <<~PATTERN
70- (send nil? {:assert_predicate :assert_not_predicate :refute_predicate} $_ ${sym} $_?)
71- PATTERN
72-
73- # @!method minitest_match(node)
74- def_node_matcher :minitest_match , <<~PATTERN
75- (send nil? {:assert_match :refute_match} $_ $_ $_?)
76- PATTERN
77-
78- # @!method minitest_nil(node)
79- def_node_matcher :minitest_nil , <<~PATTERN
80- (send nil? {:assert_nil :assert_not_nil :refute_nil} $_ $_?)
81- PATTERN
82-
83- # @!method minitest_empty(node)
84- def_node_matcher :minitest_empty , <<~PATTERN
85- (send nil? {:assert_empty :assert_not_empty :refute_empty} $_ $_?)
86- PATTERN
87-
88- def on_send ( node ) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
89- minitest_equal ( node ) do |expected , actual , failure_message |
90- on_assertion ( node , EqualAssertion . new ( expected , actual ,
91- failure_message . first ) )
92- end
93-
94- minitest_instance_of ( node ) do |expected , actual , failure_message |
95- on_assertion ( node , InstanceOfAssertion . new ( expected , actual ,
96- failure_message . first ) )
97- end
98-
99- minitest_predicate ( node ) do |subject , predicate , failure_message |
100- next unless predicate . value . end_with? ( '?' )
101-
102- on_assertion ( node , PredicateAssertion . new ( predicate , subject ,
103- failure_message . first ) )
104- end
105-
106- minitest_includes ( node ) do |collection , expected , failure_message |
107- on_assertion ( node , IncludesAssertion . new ( expected , collection ,
108- failure_message . first ) )
109- end
110-
111- minitest_match ( node ) do |matcher , actual , failure_message |
112- on_assertion ( node , MatchAssertion . new ( matcher , actual ,
113- failure_message . first ) )
114- end
115-
116- minitest_nil ( node ) do |actual , failure_message |
117- on_assertion ( node , NilAssertion . new ( nil , actual ,
118- failure_message . first ) )
119- end
120-
121- minitest_empty ( node ) do |actual , failure_message |
122- on_assertion ( node , EmptyAssertion . new ( nil , actual ,
123- failure_message . first ) )
124- end
125- end
126-
127- def on_assertion ( node , assertion )
128- preferred = assertion . replaced ( node )
129- add_offense ( node , message : message ( preferred ) ) do |corrector |
130- corrector . replace ( node , preferred )
131- end
132- end
133-
134- def message ( preferred )
135- format ( MSG , prefer : preferred )
136- end
137-
13829 # :nodoc:
13930 class BasicAssertion
14031 def initialize ( expected , actual , fail_message )
@@ -151,10 +42,32 @@ def replaced(node)
15142 "expect(#{ @actual } ).#{ runner } (#{ assertion } , #{ @fail_message } )"
15243 end
15344 end
45+
46+ def negated? ( node )
47+ raise NotImplementedError
48+ end
49+
50+ def assertion
51+ raise NotImplementedError
52+ end
15453 end
15554
15655 # :nodoc:
15756 class EqualAssertion < BasicAssertion
57+ MATCHERS = %i[
58+ assert_equal
59+ assert_not_equal
60+ refute_equal
61+ ] . freeze
62+
63+ NODE_MATCHER_PATTERN = <<~PATTERN
64+ (send nil? {:assert_equal :assert_not_equal :refute_equal} $_ $_ $_?)
65+ PATTERN
66+
67+ def self . match ( expected , actual , failure_message )
68+ new ( expected , actual , failure_message . first )
69+ end
70+
15871 def negated? ( node )
15972 !node . method? ( :assert_equal )
16073 end
@@ -166,6 +79,20 @@ def assertion
16679
16780 # :nodoc:
16881 class InstanceOfAssertion < BasicAssertion
82+ MATCHERS = %i[
83+ assert_instance_of
84+ assert_not_instance_of
85+ refute_instance_of
86+ ] . freeze
87+
88+ NODE_MATCHER_PATTERN = <<~PATTERN
89+ (send nil? {:assert_instance_of :assert_not_instance_of :refute_instance_of} $_ $_ $_?)
90+ PATTERN
91+
92+ def self . match ( expected , actual , failure_message )
93+ new ( expected , actual , failure_message . first )
94+ end
95+
16996 def negated? ( node )
17097 !node . method? ( :assert_instance_of )
17198 end
@@ -177,6 +104,20 @@ def assertion
177104
178105 # :nodoc:
179106 class IncludesAssertion < BasicAssertion
107+ MATCHERS = %i[
108+ assert_includes
109+ assert_not_includes
110+ refute_includes
111+ ] . freeze
112+
113+ NODE_MATCHER_PATTERN = <<~PATTERN
114+ (send nil? {:assert_includes :assert_not_includes :refute_includes} $_ $_ $_?)
115+ PATTERN
116+
117+ def self . match ( collection , expected , failure_message )
118+ new ( expected , collection , failure_message . first )
119+ end
120+
180121 def negated? ( node )
181122 !node . method? ( :assert_includes )
182123 end
@@ -188,6 +129,22 @@ def assertion
188129
189130 # :nodoc:
190131 class PredicateAssertion < BasicAssertion
132+ MATCHERS = %i[
133+ assert_predicate
134+ assert_not_predicate
135+ refute_predicate
136+ ] . freeze
137+
138+ NODE_MATCHER_PATTERN = <<~PATTERN
139+ (send nil? {:assert_predicate :assert_not_predicate :refute_predicate} $_ ${sym} $_?)
140+ PATTERN
141+
142+ def self . match ( subject , predicate , failure_message )
143+ return nil unless predicate . value . end_with? ( '?' )
144+
145+ new ( predicate , subject , failure_message . first )
146+ end
147+
191148 def negated? ( node )
192149 !node . method? ( :assert_predicate )
193150 end
@@ -199,6 +156,19 @@ def assertion
199156
200157 # :nodoc:
201158 class MatchAssertion < BasicAssertion
159+ MATCHERS = %i[
160+ assert_match
161+ refute_match
162+ ] . freeze
163+
164+ NODE_MATCHER_PATTERN = <<~PATTERN
165+ (send nil? {:assert_match :refute_match} $_ $_ $_?)
166+ PATTERN
167+
168+ def self . match ( matcher , actual , failure_message )
169+ new ( matcher , actual , failure_message . first )
170+ end
171+
202172 def negated? ( node )
203173 !node . method? ( :assert_match )
204174 end
@@ -210,6 +180,20 @@ def assertion
210180
211181 # :nodoc:
212182 class NilAssertion < BasicAssertion
183+ MATCHERS = %i[
184+ assert_nil
185+ assert_not_nil
186+ refute_nil
187+ ] . freeze
188+
189+ NODE_MATCHER_PATTERN = <<~PATTERN
190+ (send nil? {:assert_nil :assert_not_nil :refute_nil} $_ $_?)
191+ PATTERN
192+
193+ def self . match ( actual , failure_message )
194+ new ( nil , actual , failure_message . first )
195+ end
196+
213197 def negated? ( node )
214198 !node . method? ( :assert_nil )
215199 end
@@ -221,6 +205,20 @@ def assertion
221205
222206 # :nodoc:
223207 class EmptyAssertion < BasicAssertion
208+ MATCHERS = %i[
209+ assert_empty
210+ assert_not_empty
211+ refute_empty
212+ ] . freeze
213+
214+ NODE_MATCHER_PATTERN = <<~PATTERN
215+ (send nil? {:assert_empty :assert_not_empty :refute_empty} $_ $_?)
216+ PATTERN
217+
218+ def self . match ( actual , failure_message )
219+ new ( nil , actual , failure_message . first )
220+ end
221+
224222 def negated? ( node )
225223 !node . method? ( :assert_empty )
226224 end
@@ -229,6 +227,48 @@ def assertion
229227 'be_empty'
230228 end
231229 end
230+
231+ MSG = 'Use `%<prefer>s`.'
232+
233+ # TODO: replace with `BasicAssertion.subclasses` in Ruby 3.1+
234+ ASSERTION_MATCHERS = constants ( false ) . filter_map do |c |
235+ const = const_get ( c )
236+
237+ const if const . is_a? ( Class ) && const . superclass == BasicAssertion
238+ end
239+
240+ RESTRICT_ON_SEND = ASSERTION_MATCHERS . flat_map { |m | m ::MATCHERS }
241+
242+ ASSERTION_MATCHERS . each do |m |
243+ name = m . name . split ( '::' ) . last
244+
245+ def_node_matcher "minitest_#{ name } " . to_sym , m ::NODE_MATCHER_PATTERN
246+ end
247+
248+ def on_send ( node )
249+ ASSERTION_MATCHERS . each do |m |
250+ name = m . name . split ( '::' ) . last
251+
252+ public_send ( "minitest_#{ name } " . to_sym , node ) do |*args |
253+ assertion = m . match ( *args )
254+
255+ next if assertion . nil?
256+
257+ on_assertion ( node , assertion )
258+ end
259+ end
260+ end
261+
262+ def on_assertion ( node , assertion )
263+ preferred = assertion . replaced ( node )
264+ add_offense ( node , message : message ( preferred ) ) do |corrector |
265+ corrector . replace ( node , preferred )
266+ end
267+ end
268+
269+ def message ( preferred )
270+ format ( MSG , prefer : preferred )
271+ end
232272 end
233273 end
234274 end
0 commit comments