rubocop-rspec 2.29.1 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -3
  3. data/README.md +21 -5
  4. data/config/default.yml +64 -269
  5. data/config/obsoletion.yml +20 -21
  6. data/lib/rubocop/cop/rspec/around_block.rb +2 -4
  7. data/lib/rubocop/cop/rspec/base.rb +0 -1
  8. data/lib/rubocop/cop/rspec/be_eq.rb +1 -1
  9. data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
  10. data/lib/rubocop/cop/rspec/be_nil.rb +4 -0
  11. data/lib/rubocop/cop/rspec/change_by_zero.rb +4 -5
  12. data/lib/rubocop/cop/rspec/contain_exactly.rb +1 -0
  13. data/lib/rubocop/cop/rspec/context_wording.rb +15 -9
  14. data/lib/rubocop/cop/rspec/dialect.rb +13 -0
  15. data/lib/rubocop/cop/rspec/empty_example_group.rb +2 -0
  16. data/lib/rubocop/cop/rspec/empty_metadata.rb +1 -0
  17. data/lib/rubocop/cop/rspec/example_wording.rb +3 -5
  18. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -1
  19. data/lib/rubocop/cop/rspec/expect_actual.rb +3 -3
  20. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  21. data/lib/rubocop/cop/rspec/expect_in_let.rb +42 -0
  22. data/lib/rubocop/cop/rspec/focus.rb +14 -16
  23. data/lib/rubocop/cop/rspec/implicit_expect.rb +3 -3
  24. data/lib/rubocop/cop/rspec/implicit_subject.rb +8 -0
  25. data/lib/rubocop/cop/rspec/indexed_let.rb +6 -3
  26. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
  27. data/lib/rubocop/cop/rspec/match_array.rb +1 -0
  28. data/lib/rubocop/cop/rspec/message_spies.rb +4 -0
  29. data/lib/rubocop/cop/rspec/metadata_style.rb +1 -6
  30. data/lib/rubocop/cop/rspec/missing_expectation_target_method.rb +54 -0
  31. data/lib/rubocop/cop/rspec/mixin/metadata.rb +5 -8
  32. data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +7 -0
  33. data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
  34. data/lib/rubocop/cop/rspec/multiple_expectations.rb +4 -4
  35. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +4 -5
  36. data/lib/rubocop/cop/rspec/named_subject.rb +5 -2
  37. data/lib/rubocop/cop/rspec/nested_groups.rb +2 -1
  38. data/lib/rubocop/cop/rspec/pending_without_reason.rb +0 -5
  39. data/lib/rubocop/cop/rspec/predicate_matcher.rb +25 -11
  40. data/lib/rubocop/cop/rspec/remove_const.rb +0 -1
  41. data/lib/rubocop/cop/rspec/repeated_subject_call.rb +1 -0
  42. data/lib/rubocop/cop/rspec/return_from_stub.rb +5 -4
  43. data/lib/rubocop/cop/rspec/scattered_setup.rb +7 -1
  44. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +3 -4
  45. data/lib/rubocop/cop/rspec/sort_metadata.rb +22 -8
  46. data/lib/rubocop/cop/rspec/stubbed_mock.rb +15 -10
  47. data/lib/rubocop/cop/rspec/subject_stub.rb +2 -2
  48. data/lib/rubocop/cop/rspec/unspecified_exception.rb +21 -14
  49. data/lib/rubocop/cop/rspec/verified_double_reference.rb +14 -53
  50. data/lib/rubocop/cop/rspec/void_expect.rb +6 -1
  51. data/lib/rubocop/cop/rspec_cops.rb +2 -25
  52. data/lib/rubocop/rspec/concept.rb +0 -1
  53. data/lib/rubocop/rspec/config_formatter.rb +4 -32
  54. data/lib/rubocop/rspec/cop/generator.rb +25 -0
  55. data/lib/rubocop/rspec/description_extractor.rb +2 -2
  56. data/lib/rubocop/rspec/hook.rb +1 -1
  57. data/lib/rubocop/rspec/language.rb +0 -1
  58. data/lib/rubocop/rspec/node.rb +1 -1
  59. data/lib/rubocop/rspec/plugin.rb +37 -0
  60. data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +1 -1
  61. data/lib/rubocop/rspec/version.rb +1 -1
  62. data/lib/rubocop/rspec/wording.rb +2 -4
  63. data/lib/rubocop/rspec.rb +0 -7
  64. data/lib/rubocop-rspec.rb +2 -20
  65. metadata +18 -62
  66. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +0 -39
  67. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +0 -104
  68. data/lib/rubocop/cop/rspec/capybara/match_style.rb +0 -38
  69. data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +0 -33
  70. data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +0 -29
  71. data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +0 -24
  72. data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +0 -35
  73. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +0 -36
  74. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +0 -35
  75. data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +0 -50
  76. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +0 -40
  77. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +0 -29
  78. data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +0 -33
  79. data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +0 -55
  80. data/lib/rubocop/cop/rspec/file_path.rb +0 -179
  81. data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +0 -27
  82. data/lib/rubocop/cop/rspec/rails/have_http_status.rb +0 -35
  83. data/lib/rubocop/cop/rspec/rails/http_status.rb +0 -61
  84. data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +0 -62
  85. data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +0 -39
  86. data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +0 -39
  87. data/lib/rubocop/cop/rspec/rails/travel_around.rb +0 -34
  88. data/lib/rubocop/rspec/inject.rb +0 -18
  89. data/lib/rubocop/rspec/language/node_pattern.rb +0 -48
@@ -94,11 +94,6 @@ module RuboCop
94
94
  (send #rspec? ${#ExampleGroups.skipped} ...)
95
95
  PATTERN
96
96
 
97
- # @!method pending_step_without_reason?(node)
98
- def_node_matcher :pending_step_without_reason?, <<~PATTERN
99
- (send nil? {:skip :pending})
100
- PATTERN
101
-
102
97
  def on_send(node)
103
98
  on_pending_by_metadata(node)
104
99
  return unless (parent = parent_node(node))
@@ -15,6 +15,8 @@ module RuboCop
15
15
 
16
16
  def check_inflected(node)
17
17
  predicate_in_actual?(node) do |predicate, to, matcher|
18
+ next if cannot_replace_predicate?(predicate)
19
+
18
20
  msg = message_inflected(predicate)
19
21
  add_offense(node, message: msg) do |corrector|
20
22
  remove_predicate(corrector, predicate)
@@ -32,12 +34,16 @@ module RuboCop
32
34
  (block $(send !nil? #predicate? ...) ...)
33
35
  $(send !nil? #predicate? ...)})
34
36
  $#Runners.all
35
- $#boolean_matcher?)
37
+ $#boolean_matcher? ...)
36
38
  PATTERN
37
39
 
40
+ def cannot_replace_predicate?(send_node)
41
+ send_node.method?(:respond_to?) && send_node.arguments.length > 1
42
+ end
43
+
38
44
  # @!method be_bool?(node)
39
45
  def_node_matcher :be_bool?, <<~PATTERN
40
- (send nil? {:be :eq :eql :equal} {true false})
46
+ (send nil? {:be :eq :eql :equal} boolean)
41
47
  PATTERN
42
48
 
43
49
  # @!method be_boolthy?(node)
@@ -63,7 +69,6 @@ module RuboCop
63
69
  matcher_name: to_predicate_matcher(predicate.method_name))
64
70
  end
65
71
 
66
- # rubocop:disable Metrics/MethodLength
67
72
  def to_predicate_matcher(name)
68
73
  case name = name.to_s
69
74
  when 'is_a?'
@@ -80,7 +85,6 @@ module RuboCop
80
85
  "be_#{name[0..-2]}"
81
86
  end
82
87
  end
83
- # rubocop:enable Metrics/MethodLength
84
88
 
85
89
  def remove_predicate(corrector, predicate)
86
90
  range = predicate.loc.dot.with(
@@ -106,12 +110,16 @@ module RuboCop
106
110
 
107
111
  def true?(to_symbol, matcher)
108
112
  result = case matcher.method_name
109
- when :be, :eq
113
+ when :be, :eq, :eql, :equal
110
114
  matcher.first_argument.true_type?
111
115
  when :be_truthy, :a_truthy_value
112
116
  true
113
117
  when :be_falsey, :be_falsy, :a_falsey_value, :a_falsy_value
114
118
  false
119
+ else
120
+ # :nocov:
121
+ :noop
122
+ # :nocov:
115
123
  end
116
124
  to_symbol == :to ? result : !result
117
125
  end
@@ -174,7 +182,7 @@ module RuboCop
174
182
 
175
183
  def heredoc_argument?(matcher)
176
184
  matcher.arguments.select do |arg|
177
- %i[str dstr xstr].include?(arg.type)
185
+ arg.str_type? || arg.dstr_type? || arg.xstr_type?
178
186
  end.any?(&:heredoc?)
179
187
  end
180
188
 
@@ -183,8 +191,12 @@ module RuboCop
183
191
  (send
184
192
  (send nil? :expect $!nil?)
185
193
  #Runners.all
186
- {$(send nil? #predicate_matcher_name? ...)
187
- (block $(send nil? #predicate_matcher_name? ...) ...)})
194
+ {
195
+ $(send nil? #predicate_matcher_name? ...)
196
+ (block $(send nil? #predicate_matcher_name? ...) ...)
197
+ }
198
+ ...
199
+ )
188
200
  PATTERN
189
201
 
190
202
  # @!method predicate_matcher_block?(node)
@@ -229,7 +241,6 @@ module RuboCop
229
241
  corrector.insert_after(actual, ".#{predicate}" + args + block)
230
242
  end
231
243
 
232
- # rubocop:disable Metrics/MethodLength
233
244
  def to_predicate_method(matcher)
234
245
  case matcher = matcher.to_s
235
246
  when 'be_a', 'be_an', 'be_a_kind_of', 'a_kind_of', 'be_kind_of'
@@ -246,7 +257,6 @@ module RuboCop
246
257
  "#{matcher[/\Abe_(.+)/, 1]}?"
247
258
  end
248
259
  end
249
- # rubocop:enable Metrics/MethodLength
250
260
 
251
261
  def replacement_matcher(node)
252
262
  case [cop_config['Strict'], node.method?(:to)]
@@ -256,7 +266,7 @@ module RuboCop
256
266
  'be(false)'
257
267
  when [false, true]
258
268
  'be_truthy'
259
- when [false, false]
269
+ else
260
270
  'be_falsey'
261
271
  end
262
272
  end
@@ -325,6 +335,10 @@ module RuboCop
325
335
  check_inflected(node)
326
336
  when :explicit
327
337
  check_explicit(node)
338
+ else
339
+ # :nocov:
340
+ :noop
341
+ # :nocov:
328
342
  end
329
343
  end
330
344
 
@@ -17,7 +17,6 @@ module RuboCop
17
17
  #
18
18
  class RemoveConst < Base
19
19
  include RuboCop::RSpec::Language
20
- extend RuboCop::RSpec::Language::NodePattern
21
20
 
22
21
  MSG = 'Do not use remove_const in specs. ' \
23
22
  'Consider using e.g. `stub_const`.'
@@ -72,6 +72,7 @@ module RuboCop
72
72
 
73
73
  def detect_offense(subject_node)
74
74
  return if subject_node.chained?
75
+ return if subject_node.parent.send_type?
75
76
  return unless (block_node = expect_block(subject_node))
76
77
 
77
78
  add_offense(block_node)
@@ -80,10 +80,10 @@ module RuboCop
80
80
 
81
81
  def check_block_body(block)
82
82
  body = block.body
83
- unless dynamic?(body) # rubocop:disable Style/GuardClause
84
- add_offense(block.loc.begin, message: MSG_AND_RETURN) do |corrector|
85
- BlockBodyCorrector.new(block).call(corrector)
86
- end
83
+ return if dynamic?(body)
84
+
85
+ add_offense(block.loc.begin, message: MSG_AND_RETURN) do |corrector|
86
+ BlockBodyCorrector.new(block).call(corrector)
87
87
  end
88
88
  end
89
89
 
@@ -162,6 +162,7 @@ module RuboCop
162
162
  end
163
163
 
164
164
  NULL_BLOCK_BODY = Struct.new(:loc, :source).new(nil, 'nil')
165
+ private_constant :NULL_BLOCK_BODY
165
166
  end
166
167
  end
167
168
  end
@@ -23,6 +23,7 @@ module RuboCop
23
23
  # end
24
24
  #
25
25
  class ScatteredSetup < Base
26
+ include FinalEndLocation
26
27
  include RangeHelp
27
28
  extend AutoCorrector
28
29
 
@@ -75,8 +76,13 @@ module RuboCop
75
76
  def autocorrect(corrector, first_occurrence, occurrence)
76
77
  return if first_occurrence == occurrence || !first_occurrence.body
77
78
 
79
+ # Take heredocs into account
80
+ body = occurrence.body&.source_range&.with(
81
+ end_pos: final_end_location(occurrence).begin_pos
82
+ )
83
+
78
84
  corrector.insert_after(first_occurrence.body,
79
- "\n#{occurrence.body.source}")
85
+ "\n#{body&.source}")
80
86
  corrector.remove(range_by_whole_lines(occurrence.source_range,
81
87
  include_final_newline: true))
82
88
  end
@@ -67,11 +67,10 @@ module RuboCop
67
67
  end
68
68
 
69
69
  def autocorrect_hash_arg(corrector, arg)
70
- key, value = *arg.children.first
71
-
72
- corrector.replace(arg, key_to_arg(key))
70
+ pair = arg.pairs.first
71
+ corrector.replace(arg, key_to_arg(pair.key))
73
72
  corrector.insert_after(arg.parent.loc.end,
74
- ".and_return(#{value.source})")
73
+ ".and_return(#{pair.value.source})")
75
74
  end
76
75
 
77
76
  def autocorrect_array_arg(corrector, arg)
@@ -5,6 +5,8 @@ module RuboCop
5
5
  module RSpec
6
6
  # Sort RSpec metadata alphabetically.
7
7
  #
8
+ # Only the trailing metadata is sorted.
9
+ #
8
10
  # @example
9
11
  # # bad
10
12
  # describe 'Something', :b, :a
@@ -16,6 +18,9 @@ module RuboCop
16
18
  # context 'Something', baz: true, foo: 'bar'
17
19
  # it 'works', :a, :b, baz: true, foo: 'bar'
18
20
  #
21
+ # # good, trailing metadata is sorted
22
+ # describe 'Something', 'description', :a, :b, :z
23
+ # context 'Something', :z, variable, :a, :b
19
24
  class SortMetadata < Base
20
25
  extend AutoCorrector
21
26
  include Metadata
@@ -23,8 +28,14 @@ module RuboCop
23
28
 
24
29
  MSG = 'Sort metadata alphabetically.'
25
30
 
26
- def on_metadata(symbols, hash)
31
+ # @!method match_ambiguous_trailing_metadata?(node)
32
+ def_node_matcher :match_ambiguous_trailing_metadata?, <<~PATTERN
33
+ (send _ _ _ ... !{hash sym str dstr xstr})
34
+ PATTERN
35
+
36
+ def on_metadata(args, hash)
27
37
  pairs = hash&.pairs || []
38
+ symbols = trailing_symbols(args)
28
39
  return if sorted?(symbols, pairs)
29
40
 
30
41
  crime_scene = crime_scene(symbols, pairs)
@@ -35,6 +46,15 @@ module RuboCop
35
46
 
36
47
  private
37
48
 
49
+ def trailing_symbols(args)
50
+ args = args[...-1] if last_arg_could_be_a_hash?(args)
51
+ args.reverse.take_while(&:sym_type?).reverse
52
+ end
53
+
54
+ def last_arg_could_be_a_hash?(args)
55
+ args.last && match_ambiguous_trailing_metadata?(args.last.parent)
56
+ end
57
+
38
58
  def crime_scene(symbols, pairs)
39
59
  metadata = symbols + pairs
40
60
 
@@ -57,13 +77,7 @@ module RuboCop
57
77
  end
58
78
 
59
79
  def sort_symbols(symbols)
60
- symbols.sort_by do |symbol|
61
- if %i[str sym].include?(symbol.type)
62
- symbol.value.to_s.downcase
63
- else
64
- symbol.source.downcase
65
- end
66
- end
80
+ symbols.sort_by { |symbol| symbol.value.to_s.downcase }
67
81
  end
68
82
  end
69
83
  end
@@ -14,8 +14,9 @@ module RuboCop
14
14
  # expect(foo).to receive(:bar).with(42)
15
15
  #
16
16
  class StubbedMock < Base
17
- MSG = 'Prefer `%<replacement>s` over `%<method_name>s` when ' \
17
+ MSG = 'Prefer %<replacement>s over `%<method_name>s` when ' \
18
18
  'configuring a response.'
19
+ RESTRICT_ON_SEND = %i[to].freeze
19
20
 
20
21
  # @!method message_expectation?(node)
21
22
  # Match message expectation matcher
@@ -133,10 +134,10 @@ module RuboCop
133
134
  }
134
135
  PATTERN
135
136
 
136
- RESTRICT_ON_SEND = %i[to].freeze
137
-
138
137
  def on_send(node)
139
- expectation(node, &method(:on_expectation))
138
+ expectation(node) do |expectation, method_name, matcher|
139
+ on_expectation(expectation, method_name, matcher)
140
+ end
140
141
  end
141
142
 
142
143
  private
@@ -153,19 +154,23 @@ module RuboCop
153
154
  end
154
155
 
155
156
  def msg(method_name)
156
- format(MSG,
157
- method_name: method_name,
158
- replacement: replacement(method_name))
157
+ format(
158
+ MSG,
159
+ method_name: method_name,
160
+ replacement: replacement(method_name)
161
+ )
159
162
  end
160
163
 
161
164
  def replacement(method_name)
162
165
  case method_name
163
166
  when :expect
164
- :allow
167
+ '`allow`'
165
168
  when :is_expected
166
- 'allow(subject)'
169
+ '`allow(subject)`'
167
170
  when :expect_any_instance_of
168
- :allow_any_instance_of
171
+ '`allow_any_instance_of`'
172
+ else
173
+ 'an allow statement'
169
174
  end
170
175
  end
171
176
  end
@@ -113,8 +113,8 @@ module RuboCop
113
113
  PATTERN
114
114
 
115
115
  def on_top_level_group(node)
116
- @explicit_subjects = find_all_explicit(node, &method(:subject?))
117
- @subject_overrides = find_all_explicit(node, &method(:let?))
116
+ @explicit_subjects = find_all_explicit(node) { |n| subject?(n) }
117
+ @subject_overrides = find_all_explicit(node) { |n| let?(n) }
118
118
 
119
119
  find_subject_expectations(node) do |stub|
120
120
  add_offense(stub)
@@ -32,34 +32,41 @@ module RuboCop
32
32
  #
33
33
  class UnspecifiedException < Base
34
34
  MSG = 'Specify the exception being captured'
35
- RESTRICT_ON_SEND = %i[to].freeze
36
35
 
37
- # @!method empty_raise_error_or_exception(node)
38
- def_node_matcher :empty_raise_error_or_exception, <<~PATTERN
39
- (send
40
- (block
41
- (send nil? :expect) ...)
42
- :to
43
- (send nil? {:raise_error :raise_exception})
44
- )
36
+ RESTRICT_ON_SEND = %i[
37
+ raise_exception
38
+ raise_error
39
+ ].freeze
40
+
41
+ # @!method expect_to?(node)
42
+ def_node_matcher :expect_to?, <<~PATTERN
43
+ (send (block (send nil? :expect) ...) :to ...)
45
44
  PATTERN
46
45
 
47
46
  def on_send(node)
48
47
  return unless empty_exception_matcher?(node)
49
48
 
50
- add_offense(node.children.last)
49
+ add_offense(node)
51
50
  end
52
51
 
53
52
  private
54
53
 
55
54
  def empty_exception_matcher?(node)
56
- empty_raise_error_or_exception(node) && !block_with_args?(node.parent)
55
+ return false if node.arguments? || node.block_literal?
56
+
57
+ expect_to = find_expect_to(node)
58
+ return false unless expect_to
59
+ return false if expect_to.block_node&.arguments?
60
+
61
+ true
57
62
  end
58
63
 
59
- def block_with_args?(node)
60
- return false unless node&.block_type?
64
+ def find_expect_to(node)
65
+ node.each_ancestor.find do |ancestor|
66
+ break if ancestor.block_type?
61
67
 
62
- node.arguments?
68
+ expect_to?(ancestor)
69
+ end
63
70
  end
64
71
  end
65
72
  end
@@ -5,14 +5,14 @@ module RuboCop
5
5
  module RSpec
6
6
  # Checks for consistent verified double reference style.
7
7
  #
8
- # Only investigates references that are one of the supported styles.
9
- #
10
8
  # @see https://rspec.info/features/3-12/rspec-mocks/verifying-doubles
11
9
  #
12
- # This cop can be configured in your configuration using the
13
- # `EnforcedStyle` option and supports `--auto-gen-config`.
10
+ # @safety
11
+ # This cop is unsafe because the correction requires loading the class.
12
+ # Loading before stubbing causes RSpec to only allow instance methods
13
+ # to be stubbed.
14
14
  #
15
- # @example `EnforcedStyle: constant` (default)
15
+ # @example
16
16
  # # bad
17
17
  # let(:foo) do
18
18
  # instance_double('ClassName', method_name: 'returned_value')
@@ -23,18 +23,7 @@ module RuboCop
23
23
  # instance_double(ClassName, method_name: 'returned_value')
24
24
  # end
25
25
  #
26
- # @example `EnforcedStyle: string`
27
- # # bad
28
- # let(:foo) do
29
- # instance_double(ClassName, method_name: 'returned_value')
30
- # end
31
- #
32
- # # good
33
- # let(:foo) do
34
- # instance_double('ClassName', method_name: 'returned_value')
35
- # end
36
- #
37
- # @example Reference is not in the supported style list. No enforcement
26
+ # @example Reference is any dynamic variable. No enforcement
38
27
  #
39
28
  # # good
40
29
  # let(:foo) do
@@ -42,9 +31,9 @@ module RuboCop
42
31
  # end
43
32
  class VerifiedDoubleReference < Base
44
33
  extend AutoCorrector
45
- include ConfigurableEnforcedStyle
46
34
 
47
- MSG = 'Use a %<style>s class reference for verified doubles.'
35
+ MSG = 'Use a constant class reference for verified doubles. ' \
36
+ 'String references are not verifying unless the class is loaded.'
48
37
 
49
38
  RESTRICT_ON_SEND = Set[
50
39
  :class_double,
@@ -57,53 +46,25 @@ module RuboCop
57
46
  :stub_model
58
47
  ].freeze
59
48
 
60
- REFERENCE_TYPE_STYLES = {
61
- str: :string,
62
- const: :constant
63
- }.freeze
64
-
65
49
  # @!method verified_double(node)
66
50
  def_node_matcher :verified_double, <<~PATTERN
67
51
  (send
68
52
  nil?
69
53
  RESTRICT_ON_SEND
70
- $_class_reference
54
+ $str
71
55
  ...)
72
56
  PATTERN
73
57
 
74
58
  def on_send(node)
75
- verified_double(node) do |class_reference|
76
- break correct_style_detected unless opposing_style?(class_reference)
77
-
78
- message = format(MSG, style: style)
79
- expression = class_reference.source_range
80
-
81
- add_offense(expression, message: message) do |corrector|
82
- offense = class_reference.source
83
- corrector.replace(expression, correct_style(offense))
84
-
85
- opposite_style_detected
59
+ verified_double(node) do |string_argument_node|
60
+ add_offense(string_argument_node) do |corrector|
61
+ autocorrect(corrector, string_argument_node)
86
62
  end
87
63
  end
88
64
  end
89
65
 
90
- private
91
-
92
- def opposing_style?(class_reference)
93
- class_reference_style = REFERENCE_TYPE_STYLES[class_reference.type]
94
-
95
- # Only enforce supported styles
96
- return false unless class_reference_style
97
-
98
- class_reference_style != style
99
- end
100
-
101
- def correct_style(offense)
102
- if style == :string
103
- "'#{offense}'"
104
- else
105
- offense.gsub(/^['"]|['"]$/, '')
106
- end
66
+ def autocorrect(corrector, node)
67
+ corrector.replace(node, node.value)
107
68
  end
108
69
  end
109
70
  end
@@ -29,12 +29,14 @@ module RuboCop
29
29
 
30
30
  def on_send(node)
31
31
  return unless expect?(node)
32
+ return unless inside_example?(node)
32
33
 
33
34
  check_expect(node)
34
35
  end
35
36
 
36
37
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
37
38
  return unless expect_block?(node)
39
+ return unless inside_example?(node)
38
40
 
39
41
  check_expect(node)
40
42
  end
@@ -49,11 +51,14 @@ module RuboCop
49
51
 
50
52
  def void?(expect)
51
53
  parent = expect.parent
52
- return true unless parent
53
54
  return true if parent.begin_type?
54
55
 
55
56
  parent.block_type? && parent.body == expect
56
57
  end
58
+
59
+ def inside_example?(node)
60
+ node.each_ancestor(:block).any? { |ancestor| example?(ancestor) }
61
+ end
57
62
  end
58
63
  end
59
64
  end
@@ -1,29 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'rspec/capybara/current_path_expectation'
4
- require_relative 'rspec/capybara/feature_methods'
5
- require_relative 'rspec/capybara/match_style'
6
- require_relative 'rspec/capybara/negation_matcher'
7
- require_relative 'rspec/capybara/specific_actions'
8
- require_relative 'rspec/capybara/specific_finders'
9
- require_relative 'rspec/capybara/specific_matcher'
10
- require_relative 'rspec/capybara/visibility_matcher'
11
-
12
- require_relative 'rspec/factory_bot/attribute_defined_statically'
13
- require_relative 'rspec/factory_bot/consistent_parentheses_style'
14
- require_relative 'rspec/factory_bot/create_list'
15
- require_relative 'rspec/factory_bot/factory_class_name'
16
- require_relative 'rspec/factory_bot/factory_name_style'
17
- require_relative 'rspec/factory_bot/syntax_methods'
18
-
19
- require_relative 'rspec/rails/avoid_setup_hook'
20
- require_relative 'rspec/rails/have_http_status'
21
- require_relative 'rspec/rails/http_status'
22
- require_relative 'rspec/rails/inferred_spec_type'
23
- require_relative 'rspec/rails/minitest_assertions'
24
- require_relative 'rspec/rails/negation_be_valid'
25
- require_relative 'rspec/rails/travel_around'
26
-
27
3
  require_relative 'rspec/align_left_let_brace'
28
4
  require_relative 'rspec/align_right_let_brace'
29
5
  require_relative 'rspec/any_instance'
@@ -63,8 +39,8 @@ require_relative 'rspec/excessive_docstring_spacing'
63
39
  require_relative 'rspec/expect_actual'
64
40
  require_relative 'rspec/expect_change'
65
41
  require_relative 'rspec/expect_in_hook'
42
+ require_relative 'rspec/expect_in_let'
66
43
  require_relative 'rspec/expect_output'
67
- require_relative 'rspec/file_path'
68
44
  require_relative 'rspec/focus'
69
45
  require_relative 'rspec/hook_argument'
70
46
  require_relative 'rspec/hooks_before_examples'
@@ -88,6 +64,7 @@ require_relative 'rspec/message_expectation'
88
64
  require_relative 'rspec/message_spies'
89
65
  require_relative 'rspec/metadata_style'
90
66
  require_relative 'rspec/missing_example_group_argument'
67
+ require_relative 'rspec/missing_expectation_target_method'
91
68
  require_relative 'rspec/multiple_describes'
92
69
  require_relative 'rspec/multiple_expectations'
93
70
  require_relative 'rspec/multiple_memoized_helpers'
@@ -5,7 +5,6 @@ module RuboCop
5
5
  # Wrapper for RSpec DSL methods
6
6
  class Concept
7
7
  extend RuboCop::NodePattern::Macros
8
- extend Language::NodePattern
9
8
  include Language
10
9
 
11
10
  def initialize(node)
@@ -6,31 +6,7 @@ module RuboCop
6
6
  module RSpec
7
7
  # Builds a YAML config file from two config hashes
8
8
  class ConfigFormatter
9
- EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
10
- SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails)
11
- EXTRACTED_COPS = %(
12
- RSpec/Capybara/CurrentPathExpectation
13
- RSpec/Capybara/MatchStyle
14
- RSpec/Capybara/NegationMatcher
15
- RSpec/Capybara/SpecificActions
16
- RSpec/Capybara/SpecificFinders
17
- RSpec/Capybara/SpecificMatcher
18
- RSpec/Capybara/VisibilityMatcher
19
- RSpec/FactoryBot/AttributeDefinedStatically
20
- RSpec/FactoryBot/ConsistentParenthesesStyle
21
- RSpec/FactoryBot/CreateList
22
- RSpec/FactoryBot/FactoryClassName
23
- RSpec/FactoryBot/FactoryNameStyle
24
- RSpec/FactoryBot/SyntaxMethods
25
- RSpec/Rails/AvoidSetupHook
26
- RSpec/Rails/HaveHttpStatus
27
- RSpec/Rails/HttpStatus
28
- RSpec/Rails/InferredSpecType
29
- RSpec/Rails/MinitestAssertions
30
- RSpec/Rails/NegationBeValid
31
- RSpec/Rails/TravelAround
32
- )
33
- AMENDMENTS = %(Metrics/BlockLength)
9
+ EXTENSION_ROOT_DEPARTMENT = %r{^RSpec/}.freeze
34
10
  COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
35
11
 
36
12
  def initialize(config, descriptions)
@@ -40,19 +16,15 @@ module RuboCop
40
16
 
41
17
  def dump
42
18
  YAML.dump(unified_config)
43
- .gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
44
- .gsub(*AMENDMENTS, "\n\\0")
45
- .gsub(/^(\s+)- /, '\1 - ')
46
- .gsub('"~"', '~')
19
+ .gsub(%r{^\w+/}, "\n\\0") # Add an extra newline before each cop.
20
+ .gsub(/^(\s+)- /, '\1 - ') # Add 2 spaces before each array element.
21
+ .gsub('"~"', '~') # Don't quote tilde, YAML's null value.
47
22
  end
48
23
 
49
24
  private
50
25
 
51
26
  def unified_config
52
27
  cops.each_with_object(config.dup) do |cop, unified|
53
- next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
54
- next if EXTRACTED_COPS.include?(cop)
55
-
56
28
  replace_nil(unified[cop])
57
29
  unified[cop].merge!(descriptions.fetch(cop))
58
30
  unified[cop]['Reference'] = reference(cop)