rubocop-rspec 2.27.1 → 2.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,141 +4,58 @@ module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
6
  module Rails
7
- # Identifies redundant spec type.
8
- #
9
- # After setting up rspec-rails, you will have enabled
10
- # `config.infer_spec_type_from_file_location!` by default in
11
- # spec/rails_helper.rb. This cop works in conjunction with this config.
12
- # If you disable this config, disable this cop as well.
13
- #
14
- # @safety
15
- # This cop is marked as unsafe because
16
- # `config.infer_spec_type_from_file_location!` may not be enabled.
17
- #
18
- # @example
19
- # # bad
20
- # # spec/models/user_spec.rb
21
- # RSpec.describe User, type: :model do
22
- # end
23
- #
24
- # # good
25
- # # spec/models/user_spec.rb
26
- # RSpec.describe User do
27
- # end
28
- #
29
- # # good
30
- # # spec/models/user_spec.rb
31
- # RSpec.describe User, type: :common do
32
- # end
33
- #
34
- # @example `Inferences` configuration
35
- # # .rubocop.yml
36
- # # RSpec/Rails/InferredSpecType:
37
- # # Inferences:
38
- # # services: service
39
- #
40
- # # bad
41
- # # spec/services/user_spec.rb
42
- # RSpec.describe User, type: :service do
43
- # end
44
- #
45
- # # good
46
- # # spec/services/user_spec.rb
47
- # RSpec.describe User do
48
- # end
49
- #
50
- # # good
51
- # # spec/services/user_spec.rb
52
- # RSpec.describe User, type: :common do
53
- # end
54
- class InferredSpecType < Base
55
- extend AutoCorrector
56
-
57
- MSG = 'Remove redundant spec type.'
58
-
59
- # @param [RuboCop::AST::BlockNode] node
60
- def on_block(node)
61
- return unless example_group?(node)
62
-
63
- pair_node = describe_with_type(node)
64
- return unless pair_node
65
- return unless inferred_type?(pair_node)
66
-
67
- removable_node = detect_removable_node(pair_node)
68
- add_offense(removable_node) do |corrector|
69
- autocorrect(corrector, removable_node)
70
- end
71
- end
72
- alias on_numblock on_block
73
-
74
- private
75
-
76
- # @!method describe_with_type(node)
77
- # @param [RuboCop::AST::BlockNode] node
78
- # @return [RuboCop::AST::PairNode, nil]
79
- def_node_matcher :describe_with_type, <<~PATTERN
80
- (block
81
- (send #rspec? #ExampleGroups.all
82
- ...
83
- (hash <$(pair (sym :type) sym) ...>)
84
- )
85
- ...
86
- )
87
- PATTERN
88
-
89
- # @param [RuboCop::AST::Corrector] corrector
90
- # @param [RuboCop::AST::Node] node
91
- def autocorrect(corrector, node)
92
- corrector.remove(remove_range(node))
93
- end
94
-
95
- # @param [RuboCop::AST::Node] node
96
- # @return [Parser::Source::Range]
97
- def remove_range(node)
98
- if node.left_sibling
99
- node.source_range.with(
100
- begin_pos: node.left_sibling.source_range.end_pos
101
- )
102
- elsif node.right_sibling
103
- node.source_range.with(
104
- end_pos: node.right_sibling.source_range.begin_pos
105
- )
106
- end
107
- end
108
-
109
- # @param [RuboCop::AST::PairNode] node
110
- # @return [RuboCop::AST::Node]
111
- def detect_removable_node(node)
112
- if node.parent.pairs.size == 1
113
- node.parent
114
- else
115
- node
116
- end
117
- end
118
-
119
- # @return [String]
120
- def file_path
121
- processed_source.file_path
122
- end
123
-
124
- # @param [RuboCop::AST::PairNode] node
125
- # @return [Boolean]
126
- def inferred_type?(node)
127
- inferred_type_from_file_path.inspect == node.value.source
128
- end
129
-
130
- # @return [Symbol, nil]
131
- def inferred_type_from_file_path
132
- inferences.find do |prefix, type|
133
- break type.to_sym if file_path.include?("spec/#{prefix}/")
134
- end
135
- end
136
-
137
- # @return [Hash]
138
- def inferences
139
- cop_config['Inferences'] || {}
140
- end
141
- end
7
+ # @!parse
8
+ # # Identifies redundant spec type.
9
+ # #
10
+ # # After setting up rspec-rails, you will have enabled
11
+ # # `config.infer_spec_type_from_file_location!` by default in
12
+ # # spec/rails_helper.rb. This cop works in conjunction with
13
+ # # this config.
14
+ # # If you disable this config, disable this cop as well.
15
+ # #
16
+ # # @safety
17
+ # # This cop is marked as unsafe because
18
+ # # `config.infer_spec_type_from_file_location!` may not be enabled.
19
+ # #
20
+ # # @example
21
+ # # # bad
22
+ # # # spec/models/user_spec.rb
23
+ # # RSpec.describe User, type: :model do
24
+ # # end
25
+ # #
26
+ # # # good
27
+ # # # spec/models/user_spec.rb
28
+ # # RSpec.describe User do
29
+ # # end
30
+ # #
31
+ # # # good
32
+ # # # spec/models/user_spec.rb
33
+ # # RSpec.describe User, type: :common do
34
+ # # end
35
+ # #
36
+ # # @example `Inferences` configuration
37
+ # # # .rubocop.yml
38
+ # # # RSpec/Rails/InferredSpecType:
39
+ # # # Inferences:
40
+ # # # services: service
41
+ # #
42
+ # # # bad
43
+ # # # spec/services/user_spec.rb
44
+ # # RSpec.describe User, type: :service do
45
+ # # end
46
+ # #
47
+ # # # good
48
+ # # # spec/services/user_spec.rb
49
+ # # RSpec.describe User do
50
+ # # end
51
+ # #
52
+ # # # good
53
+ # # # spec/services/user_spec.rb
54
+ # # RSpec.describe User, type: :common do
55
+ # # end
56
+ # #
57
+ # class InferredSpecType < RuboCop::Cop::RSpec::Base; end
58
+ InferredSpecType = ::RuboCop::Cop::RSpecRails::InferredSpecType
142
59
  end
143
60
  end
144
61
  end
@@ -4,348 +4,35 @@ module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
6
  module Rails
7
- # Check if using Minitest-like matchers.
8
- #
9
- # Check the use of minitest-like matchers
10
- # starting with `assert_` or `refute_`.
11
- #
12
- # @example
13
- # # bad
14
- # assert_equal(a, b)
15
- # assert_equal a, b, "must be equal"
16
- # assert_not_includes a, b
17
- # refute_equal(a, b)
18
- # assert_nil a
19
- # refute_empty(b)
20
- # assert_true(a)
21
- # assert_false(a)
22
- #
23
- # # good
24
- # expect(b).to eq(a)
25
- # expect(b).to(eq(a), "must be equal")
26
- # expect(a).not_to include(b)
27
- # expect(b).not_to eq(a)
28
- # expect(a).to eq(nil)
29
- # expect(a).not_to be_empty
30
- # expect(a).to be(true)
31
- # expect(a).to be(false)
32
- #
33
- class MinitestAssertions < Base
34
- extend AutoCorrector
35
-
36
- # :nodoc:
37
- class BasicAssertion
38
- extend NodePattern::Macros
39
-
40
- attr_reader :expected, :actual, :failure_message
41
-
42
- def self.minitest_assertion
43
- raise NotImplementedError
44
- end
45
-
46
- def initialize(expected, actual, failure_message)
47
- @expected = expected&.source
48
- @actual = actual.source
49
- @failure_message = failure_message&.source
50
- end
51
-
52
- def replaced(node)
53
- runner = negated?(node) ? 'not_to' : 'to'
54
- if failure_message.nil?
55
- "expect(#{actual}).#{runner} #{assertion}"
56
- else
57
- "expect(#{actual}).#{runner}(#{assertion}, #{failure_message})"
58
- end
59
- end
60
-
61
- def negated?(node)
62
- node.method_name.start_with?('assert_not_', 'refute_')
63
- end
64
-
65
- def assertion
66
- raise NotImplementedError
67
- end
68
- end
69
-
70
- # :nodoc:
71
- class EqualAssertion < BasicAssertion
72
- MATCHERS = %i[
73
- assert_equal
74
- assert_not_equal
75
- refute_equal
76
- ].freeze
77
-
78
- # @!method self.minitest_assertion(node)
79
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
80
- (send nil? {:assert_equal :assert_not_equal :refute_equal} $_ $_ $_?)
81
- PATTERN
82
-
83
- def self.match(expected, actual, failure_message)
84
- new(expected, actual, failure_message.first)
85
- end
86
-
87
- def assertion
88
- "eq(#{expected})"
89
- end
90
- end
91
-
92
- # :nodoc:
93
- class KindOfAssertion < BasicAssertion
94
- MATCHERS = %i[
95
- assert_kind_of
96
- assert_not_kind_of
97
- refute_kind_of
98
- ].freeze
99
-
100
- # @!method self.minitest_assertion(node)
101
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
102
- (send nil? {:assert_kind_of :assert_not_kind_of :refute_kind_of} $_ $_ $_?)
103
- PATTERN
104
-
105
- def self.match(expected, actual, failure_message)
106
- new(expected, actual, failure_message.first)
107
- end
108
-
109
- def assertion
110
- "be_a_kind_of(#{expected})"
111
- end
112
- end
113
-
114
- # :nodoc:
115
- class InstanceOfAssertion < BasicAssertion
116
- MATCHERS = %i[
117
- assert_instance_of
118
- assert_not_instance_of
119
- refute_instance_of
120
- ].freeze
121
-
122
- # @!method self.minitest_assertion(node)
123
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
124
- (send nil? {:assert_instance_of :assert_not_instance_of :refute_instance_of} $_ $_ $_?)
125
- PATTERN
126
-
127
- def self.match(expected, actual, failure_message)
128
- new(expected, actual, failure_message.first)
129
- end
130
-
131
- def assertion
132
- "be_an_instance_of(#{expected})"
133
- end
134
- end
135
-
136
- # :nodoc:
137
- class IncludesAssertion < BasicAssertion
138
- MATCHERS = %i[
139
- assert_includes
140
- assert_not_includes
141
- refute_includes
142
- ].freeze
143
-
144
- # @!method self.minitest_assertion(node)
145
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
146
- (send nil? {:assert_includes :assert_not_includes :refute_includes} $_ $_ $_?)
147
- PATTERN
148
-
149
- def self.match(collection, expected, failure_message)
150
- new(expected, collection, failure_message.first)
151
- end
152
-
153
- def assertion
154
- "include(#{expected})"
155
- end
156
- end
157
-
158
- # :nodoc:
159
- class InDeltaAssertion < BasicAssertion
160
- MATCHERS = %i[
161
- assert_in_delta
162
- assert_not_in_delta
163
- refute_in_delta
164
- ].freeze
165
-
166
- # @!method self.minitest_assertion(node)
167
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
168
- (send nil? {:assert_in_delta :assert_not_in_delta :refute_in_delta} $_ $_ $_? $_?)
169
- PATTERN
170
-
171
- def self.match(expected, actual, delta, failure_message)
172
- new(expected, actual, delta.first, failure_message.first)
173
- end
174
-
175
- def initialize(expected, actual, delta, fail_message)
176
- super(expected, actual, fail_message)
177
-
178
- @delta = delta&.source || '0.001'
179
- end
180
-
181
- def assertion
182
- "be_within(#{@delta}).of(#{expected})"
183
- end
184
- end
185
-
186
- # :nodoc:
187
- class PredicateAssertion < BasicAssertion
188
- MATCHERS = %i[
189
- assert_predicate
190
- assert_not_predicate
191
- refute_predicate
192
- ].freeze
193
-
194
- # @!method self.minitest_assertion(node)
195
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
196
- (send nil? {:assert_predicate :assert_not_predicate :refute_predicate} $_ ${sym} $_?)
197
- PATTERN
198
-
199
- def self.match(subject, predicate, failure_message)
200
- return nil unless predicate.value.end_with?('?')
201
-
202
- new(predicate, subject, failure_message.first)
203
- end
204
-
205
- def assertion
206
- "be_#{expected.delete_prefix(':').delete_suffix('?')}"
207
- end
208
- end
209
-
210
- # :nodoc:
211
- class MatchAssertion < BasicAssertion
212
- MATCHERS = %i[
213
- assert_match
214
- refute_match
215
- ].freeze
216
-
217
- # @!method self.minitest_assertion(node)
218
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
219
- (send nil? {:assert_match :refute_match} $_ $_ $_?)
220
- PATTERN
221
-
222
- def self.match(matcher, actual, failure_message)
223
- new(matcher, actual, failure_message.first)
224
- end
225
-
226
- def assertion
227
- "match(#{expected})"
228
- end
229
- end
230
-
231
- # :nodoc:
232
- class NilAssertion < BasicAssertion
233
- MATCHERS = %i[
234
- assert_nil
235
- assert_not_nil
236
- refute_nil
237
- ].freeze
238
-
239
- # @!method self.minitest_assertion(node)
240
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
241
- (send nil? {:assert_nil :assert_not_nil :refute_nil} $_ $_?)
242
- PATTERN
243
-
244
- def self.match(actual, failure_message)
245
- new(nil, actual, failure_message.first)
246
- end
247
-
248
- def assertion
249
- 'eq(nil)'
250
- end
251
- end
252
-
253
- # :nodoc:
254
- class EmptyAssertion < BasicAssertion
255
- MATCHERS = %i[
256
- assert_empty
257
- assert_not_empty
258
- refute_empty
259
- ].freeze
260
-
261
- # @!method self.minitest_assertion(node)
262
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
263
- (send nil? {:assert_empty :assert_not_empty :refute_empty} $_ $_?)
264
- PATTERN
265
-
266
- def self.match(actual, failure_message)
267
- new(nil, actual, failure_message.first)
268
- end
269
-
270
- def assertion
271
- 'be_empty'
272
- end
273
- end
274
-
275
- # :nodoc:
276
- class TrueAssertion < BasicAssertion
277
- MATCHERS = %i[
278
- assert_true
279
- ].freeze
280
-
281
- # @!method self.minitest_assertion(node)
282
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
283
- (send nil? {:assert_true} $_ $_?)
284
- PATTERN
285
-
286
- def self.match(actual, failure_message)
287
- new(nil, actual, failure_message.first)
288
- end
289
-
290
- def assertion
291
- 'be(true)'
292
- end
293
- end
294
-
295
- # :nodoc:
296
- class FalseAssertion < BasicAssertion
297
- MATCHERS = %i[
298
- assert_false
299
- ].freeze
300
-
301
- # @!method self.minitest_assertion(node)
302
- def_node_matcher 'self.minitest_assertion', <<~PATTERN # rubocop:disable InternalAffairs/NodeMatcherDirective
303
- (send nil? {:assert_false} $_ $_?)
304
- PATTERN
305
-
306
- def self.match(actual, failure_message)
307
- new(nil, actual, failure_message.first)
308
- end
309
-
310
- def assertion
311
- 'be(false)'
312
- end
313
- end
314
-
315
- MSG = 'Use `%<prefer>s`.'
316
-
317
- # TODO: replace with `BasicAssertion.subclasses` in Ruby 3.1+
318
- ASSERTION_MATCHERS = constants(false).filter_map do |c|
319
- const = const_get(c)
320
-
321
- const if const.is_a?(Class) && const.superclass == BasicAssertion
322
- end
323
-
324
- RESTRICT_ON_SEND = ASSERTION_MATCHERS.flat_map { |m| m::MATCHERS }
325
-
326
- def on_send(node)
327
- ASSERTION_MATCHERS.each do |m|
328
- m.minitest_assertion(node) do |*args|
329
- assertion = m.match(*args)
330
-
331
- next if assertion.nil?
332
-
333
- on_assertion(node, assertion)
334
- end
335
- end
336
- end
337
-
338
- def on_assertion(node, assertion)
339
- preferred = assertion.replaced(node)
340
- add_offense(node, message: message(preferred)) do |corrector|
341
- corrector.replace(node, preferred)
342
- end
343
- end
344
-
345
- def message(preferred)
346
- format(MSG, prefer: preferred)
347
- end
348
- end
7
+ # @!parse
8
+ # # Check if using Minitest-like matchers.
9
+ # #
10
+ # # Check the use of minitest-like matchers
11
+ # # starting with `assert_` or `refute_`.
12
+ # #
13
+ # # @example
14
+ # # # bad
15
+ # # assert_equal(a, b)
16
+ # # assert_equal a, b, "must be equal"
17
+ # # assert_not_includes a, b
18
+ # # refute_equal(a, b)
19
+ # # assert_nil a
20
+ # # refute_empty(b)
21
+ # # assert_true(a)
22
+ # # assert_false(a)
23
+ # #
24
+ # # # good
25
+ # # expect(b).to eq(a)
26
+ # # expect(b).to(eq(a), "must be equal")
27
+ # # expect(a).not_to include(b)
28
+ # # expect(b).not_to eq(a)
29
+ # # expect(a).to eq(nil)
30
+ # # expect(a).not_to be_empty
31
+ # # expect(a).to be(true)
32
+ # # expect(a).to be(false)
33
+ # #
34
+ # class MinitestAssertions < RuboCop::Cop::RSpec::Base; end
35
+ MinitestAssertions = ::RuboCop::Cop::RSpecRails::MinitestAssertions
349
36
  end
350
37
  end
351
38
  end