rubocop-rspec 1.41.0 → 1.42.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +11 -18
  4. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +11 -18
  5. data/lib/rubocop/cop/rspec/be.rb +1 -1
  6. data/lib/rubocop/cop/rspec/be_eql.rb +5 -5
  7. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +18 -16
  8. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +8 -9
  9. data/lib/rubocop/cop/rspec/context_method.rb +5 -7
  10. data/lib/rubocop/cop/rspec/cop.rb +1 -1
  11. data/lib/rubocop/cop/rspec/described_class.rb +10 -7
  12. data/lib/rubocop/cop/rspec/dialect.rb +4 -11
  13. data/lib/rubocop/cop/rspec/empty_hook.rb +5 -9
  14. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +5 -3
  15. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +5 -5
  16. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +4 -1
  17. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +5 -5
  18. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +4 -1
  19. data/lib/rubocop/cop/rspec/example_wording.rb +6 -7
  20. data/lib/rubocop/cop/rspec/expect_actual.rb +7 -10
  21. data/lib/rubocop/cop/rspec/expect_change.rb +9 -34
  22. data/lib/rubocop/cop/rspec/expect_in_hook.rb +2 -2
  23. data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
  24. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +18 -18
  25. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +10 -16
  26. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +6 -7
  27. data/lib/rubocop/cop/rspec/hook_argument.rb +11 -17
  28. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +12 -13
  29. data/lib/rubocop/cop/rspec/implicit_expect.rb +6 -14
  30. data/lib/rubocop/cop/rspec/implicit_subject.rb +8 -5
  31. data/lib/rubocop/cop/rspec/instance_spy.rb +17 -11
  32. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +2 -5
  33. data/lib/rubocop/cop/rspec/it_behaves_like.rb +4 -5
  34. data/lib/rubocop/cop/rspec/leading_subject.rb +13 -13
  35. data/lib/rubocop/cop/rspec/let_before_examples.rb +12 -10
  36. data/lib/rubocop/cop/rspec/message_chain.rb +6 -5
  37. data/lib/rubocop/cop/rspec/message_expectation.rb +1 -1
  38. data/lib/rubocop/cop/rspec/message_spies.rb +1 -2
  39. data/lib/rubocop/cop/rspec/multiple_subjects.rb +17 -18
  40. data/lib/rubocop/cop/rspec/named_subject.rb +1 -1
  41. data/lib/rubocop/cop/rspec/not_to_not.rb +4 -5
  42. data/lib/rubocop/cop/rspec/predicate_matcher.rb +23 -53
  43. data/lib/rubocop/cop/rspec/rails/http_status.rb +4 -8
  44. data/lib/rubocop/cop/rspec/receive_counts.rb +14 -16
  45. data/lib/rubocop/cop/rspec/receive_never.rb +10 -10
  46. data/lib/rubocop/cop/rspec/return_from_stub.rb +8 -19
  47. data/lib/rubocop/cop/rspec/scattered_let.rb +7 -10
  48. data/lib/rubocop/cop/rspec/shared_context.rb +7 -20
  49. data/lib/rubocop/cop/rspec/shared_examples.rb +5 -8
  50. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +14 -17
  51. data/lib/rubocop/cop/rspec/yield.rb +13 -10
  52. data/lib/rubocop/rspec/blank_line_separation.rb +0 -8
  53. data/lib/rubocop/rspec/version.rb +1 -1
  54. metadata +4 -4
@@ -25,6 +25,7 @@ module RuboCop
25
25
  # it { should be_truthy }
26
26
  #
27
27
  class ImplicitExpect < Cop
28
+ extend AutoCorrector
28
29
  include ConfigurableEnforcedStyle
29
30
 
30
31
  MSG = 'Prefer `%<good>s` over `%<bad>s`.'
@@ -54,20 +55,11 @@ module RuboCop
54
55
  else
55
56
  opposite_style_detected
56
57
 
57
- add_offense(
58
- node,
59
- location: source_range,
60
- message: offense_message(expectation_source)
61
- )
62
- end
63
- end
64
-
65
- def autocorrect(node)
66
- lambda do |corrector|
67
- offense = offending_expect(node)
68
- replacement = replacement_source(offense.source)
69
-
70
- corrector.replace(offense, replacement)
58
+ msg = offense_message(expectation_source)
59
+ add_offense(source_range, message: msg) do |corrector|
60
+ replacement = replacement_source(expectation_source)
61
+ corrector.replace(source_range, replacement)
62
+ end
71
63
  end
72
64
  end
73
65
 
@@ -27,6 +27,7 @@ module RuboCop
27
27
  # it { expect(subject).to be_truthy }
28
28
  #
29
29
  class ImplicitSubject < Cop
30
+ extend AutoCorrector
30
31
  include ConfigurableEnforcedStyle
31
32
 
32
33
  MSG = "Don't use implicit subject."
@@ -39,10 +40,14 @@ module RuboCop
39
40
  return unless implicit_subject?(node)
40
41
  return if valid_usage?(node)
41
42
 
42
- add_offense(node)
43
+ add_offense(node) do |corrector|
44
+ autocorrect(corrector, node)
45
+ end
43
46
  end
44
47
 
45
- def autocorrect(node)
48
+ private
49
+
50
+ def autocorrect(corrector, node)
46
51
  replacement = 'expect(subject)'
47
52
  if node.method_name == :should
48
53
  replacement += '.to'
@@ -50,11 +55,9 @@ module RuboCop
50
55
  replacement += '.not_to'
51
56
  end
52
57
 
53
- ->(corrector) { corrector.replace(node.loc.selector, replacement) }
58
+ corrector.replace(node.loc.selector, replacement)
54
59
  end
55
60
 
56
- private
57
-
58
61
  def valid_usage?(node)
59
62
  example = node.ancestors.find { |parent| example?(parent) }
60
63
  return false if example.nil?
@@ -19,6 +19,8 @@ module RuboCop
19
19
  # end
20
20
  #
21
21
  class InstanceSpy < Cop
22
+ extend AutoCorrector
23
+
22
24
  MSG = 'Use `instance_spy` when you check your double '\
23
25
  'with `have_received`.'
24
26
 
@@ -43,22 +45,26 @@ module RuboCop
43
45
 
44
46
  null_double(node) do |var, receiver|
45
47
  have_received_usage(node) do |expected|
46
- add_offense(receiver) if expected == var
48
+ next if expected != var
49
+
50
+ add_offense(receiver) do |corrector|
51
+ autocorrect(corrector, receiver)
52
+ end
47
53
  end
48
54
  end
49
55
  end
50
56
 
51
- def autocorrect(node)
52
- lambda do |corrector|
53
- replacement = 'instance_spy'
54
- corrector.replace(node.loc.selector, replacement)
57
+ private
55
58
 
56
- double_source_map = node.parent.loc
57
- as_null_object_range = double_source_map
58
- .dot
59
- .join(double_source_map.selector)
60
- corrector.remove(as_null_object_range)
61
- end
59
+ def autocorrect(corrector, node)
60
+ replacement = 'instance_spy'
61
+ corrector.replace(node.loc.selector, replacement)
62
+
63
+ double_source_map = node.parent.loc
64
+ as_null_object_range = double_source_map
65
+ .dot
66
+ .join(double_source_map.selector)
67
+ corrector.remove(as_null_object_range)
62
68
  end
63
69
  end
64
70
  end
@@ -24,7 +24,8 @@ module RuboCop
24
24
 
25
25
  def on_send(node)
26
26
  invalid_predicate_matcher?(node) do |predicate|
27
- add_offense(predicate)
27
+ add_offense(predicate,
28
+ message: format(MSG, matcher: predicate.method_name))
28
29
  end
29
30
  end
30
31
 
@@ -34,10 +35,6 @@ module RuboCop
34
35
  name = name.to_s
35
36
  name.start_with?('be_', 'have_') && name.end_with?('?')
36
37
  end
37
-
38
- def message(predicate)
39
- format(MSG, matcher: predicate.method_name)
40
- end
41
38
  end
42
39
  end
43
40
  end
@@ -19,6 +19,7 @@ module RuboCop
19
19
  # # good
20
20
  # it_should_behave_like 'a foo'
21
21
  class ItBehavesLike < Cop
22
+ extend AutoCorrector
22
23
  include ConfigurableEnforcedStyle
23
24
 
24
25
  MSG = 'Prefer `%<replacement>s` over `%<original>s` when including '\
@@ -28,14 +29,12 @@ module RuboCop
28
29
 
29
30
  def on_send(node)
30
31
  example_inclusion_offense(node, alternative_style) do
31
- add_offense(node)
32
+ add_offense(node) do |corrector|
33
+ corrector.replace(node.loc.selector, style.to_s)
34
+ end
32
35
  end
33
36
  end
34
37
 
35
- def autocorrect(node)
36
- ->(corrector) { corrector.replace(node.loc.selector, style.to_s) }
37
- end
38
-
39
38
  private
40
39
 
41
40
  def message(_node)
@@ -32,6 +32,8 @@ module RuboCop
32
32
  # it { expect_something_else }
33
33
  #
34
34
  class LeadingSubject < Cop
35
+ extend AutoCorrector
36
+
35
37
  MSG = 'Declare `subject` above any other `%<offending>s` declarations.'
36
38
 
37
39
  def on_block(node)
@@ -43,27 +45,25 @@ module RuboCop
43
45
  def check_previous_nodes(node)
44
46
  node.parent.each_child_node do |sibling|
45
47
  if offending?(sibling)
46
- add_offense(
47
- node,
48
- message: format(MSG, offending: sibling.method_name)
49
- )
48
+ msg = format(MSG, offending: sibling.method_name)
49
+ add_offense(node, message: msg) do |corrector|
50
+ autocorrect(corrector, node)
51
+ end
50
52
  end
51
53
 
52
54
  break if offending?(sibling) || sibling.equal?(node)
53
55
  end
54
56
  end
55
57
 
56
- def autocorrect(node)
57
- lambda do |corrector|
58
- first_node = find_first_offending_node(node)
59
- RuboCop::RSpec::Corrector::MoveNode.new(
60
- node, corrector, processed_source
61
- ).move_before(first_node)
62
- end
63
- end
64
-
65
58
  private
66
59
 
60
+ def autocorrect(corrector, node)
61
+ first_node = find_first_offending_node(node)
62
+ RuboCop::RSpec::Corrector::MoveNode.new(
63
+ node, corrector, processed_source
64
+ ).move_before(first_node)
65
+ end
66
+
67
67
  def offending?(node)
68
68
  let?(node) || hook?(node) || example?(node)
69
69
  end
@@ -31,6 +31,8 @@ module RuboCop
31
31
  # expect(some).to be
32
32
  # end
33
33
  class LetBeforeExamples < Cop
34
+ extend AutoCorrector
35
+
34
36
  MSG = 'Move `let` before the examples in the group.'
35
37
 
36
38
  def_node_matcher :example_or_group?, <<-PATTERN
@@ -46,15 +48,6 @@ module RuboCop
46
48
  check_let_declarations(node.body) if multiline_block?(node.body)
47
49
  end
48
50
 
49
- def autocorrect(node)
50
- lambda do |corrector|
51
- first_example = find_first_example(node.parent)
52
- RuboCop::RSpec::Corrector::MoveNode.new(
53
- node, corrector, processed_source
54
- ).move_before(first_example)
55
- end
56
- end
57
-
58
51
  private
59
52
 
60
53
  def multiline_block?(block)
@@ -67,14 +60,23 @@ module RuboCop
67
60
 
68
61
  node.each_child_node do |child|
69
62
  next if child.sibling_index < first_example.sibling_index
63
+ next unless let?(child)
70
64
 
71
- add_offense(child) if let?(child)
65
+ add_offense(child) do |corrector|
66
+ autocorrect(corrector, child, first_example)
67
+ end
72
68
  end
73
69
  end
74
70
 
75
71
  def find_first_example(node)
76
72
  node.children.find { |sibling| example_or_group?(sibling) }
77
73
  end
74
+
75
+ def autocorrect(corrector, node, first_example)
76
+ RuboCop::RSpec::Corrector::MoveNode.new(
77
+ node, corrector, processed_source
78
+ ).move_before(first_example)
79
+ end
78
80
  end
79
81
  end
80
82
  end
@@ -21,11 +21,12 @@ module RuboCop
21
21
  PATTERN
22
22
 
23
23
  def on_send(node)
24
- message_chain(node) { add_offense(node, location: :selector) }
25
- end
26
-
27
- def message(node)
28
- format(MSG, method: node.method_name)
24
+ message_chain(node) do
25
+ add_offense(
26
+ node.loc.selector,
27
+ message: format(MSG, method: node.method_name)
28
+ )
29
+ end
29
30
  end
30
31
  end
31
32
  end
@@ -42,7 +42,7 @@ module RuboCop
42
42
  return correct_style_detected if preferred_style?(match)
43
43
 
44
44
  message = format(MSG, style: style)
45
- add_offense(match, location: :selector, message: message) do
45
+ add_offense(match.loc.selector, message: message) do
46
46
  opposite_style_detected
47
47
  end
48
48
  end
@@ -48,8 +48,7 @@ module RuboCop
48
48
  return correct_style_detected if preferred_style?(message_matcher)
49
49
 
50
50
  add_offense(
51
- message_matcher,
52
- location: :selector,
51
+ message_matcher.loc.selector,
53
52
  message: error_message(receiver)
54
53
  ) { opposite_style_detected }
55
54
  end
@@ -34,6 +34,7 @@ module RuboCop
34
34
  # This is enough of an edge case that people can just move this to
35
35
  # a `before` hook on their own
36
36
  class MultipleSubjects < Cop
37
+ extend AutoCorrector
37
38
  include RangeHelp
38
39
 
39
40
  MSG = 'Do not set more than one subject per example group'
@@ -44,38 +45,36 @@ module RuboCop
44
45
  subjects = RuboCop::RSpec::ExampleGroup.new(node).subjects
45
46
 
46
47
  subjects[0...-1].each do |subject|
47
- add_offense(subject)
48
+ add_offense(subject) do |corrector|
49
+ autocorrect(corrector, subject)
50
+ end
48
51
  end
49
52
  end
50
53
 
51
- def autocorrect(node)
52
- return unless node.method_name.equal?(:subject) # Ignore `subject!`
54
+ private
55
+
56
+ def autocorrect(corrector, subject)
57
+ return unless subject.method_name.equal?(:subject) # Ignore `subject!`
53
58
 
54
- if named_subject?(node)
55
- rename_autocorrect(node)
59
+ if named_subject?(subject)
60
+ rename_autocorrect(corrector, subject)
56
61
  else
57
- remove_autocorrect(node)
62
+ remove_autocorrect(corrector, subject)
58
63
  end
59
64
  end
60
65
 
61
- private
62
-
63
66
  def named_subject?(node)
64
67
  node.send_node.arguments?
65
68
  end
66
69
 
67
- def rename_autocorrect(node)
68
- lambda do |corrector|
69
- corrector.replace(node.send_node.loc.selector, 'let')
70
- end
70
+ def rename_autocorrect(corrector, node)
71
+ corrector.replace(node.send_node.loc.selector, 'let')
71
72
  end
72
73
 
73
- def remove_autocorrect(node)
74
- lambda do |corrector|
75
- range = range_by_whole_lines(node.source_range,
76
- include_final_newline: true)
77
- corrector.remove(range)
78
- end
74
+ def remove_autocorrect(corrector, node)
75
+ range = range_by_whole_lines(node.source_range,
76
+ include_final_newline: true)
77
+ corrector.remove(range)
79
78
  end
80
79
  end
81
80
  end
@@ -62,7 +62,7 @@ module RuboCop
62
62
  return if !rspec_block?(node) || ignored_shared_example?(node)
63
63
 
64
64
  subject_usage(node) do |subject_node|
65
- add_offense(subject_node, location: :selector)
65
+ add_offense(subject_node.loc.selector)
66
66
  end
67
67
  end
68
68
 
@@ -16,6 +16,7 @@ module RuboCop
16
16
  # expect(false).not_to be_true
17
17
  # end
18
18
  class NotToNot < Cop
19
+ extend AutoCorrector
19
20
  include ConfigurableEnforcedStyle
20
21
 
21
22
  MSG = 'Prefer `%<replacement>s` over `%<original>s`.'
@@ -24,14 +25,12 @@ module RuboCop
24
25
 
25
26
  def on_send(node)
26
27
  not_to_not_offense(node, alternative_style) do
27
- add_offense(node, location: :selector)
28
+ add_offense(node.loc.selector) do |corrector|
29
+ corrector.replace(node.loc.selector, style.to_s)
30
+ end
28
31
  end
29
32
  end
30
33
 
31
- def autocorrect(node)
32
- ->(corrector) { corrector.replace(node.loc.selector, style.to_s) }
33
- end
34
-
35
34
  private
36
35
 
37
36
  def message(_node)
@@ -14,11 +14,14 @@ module RuboCop
14
14
  private
15
15
 
16
16
  def check_inflected(node)
17
- predicate_in_actual?(node) do |predicate|
18
- add_offense(
19
- node,
20
- message: message_inflected(predicate)
21
- )
17
+ predicate_in_actual?(node) do |predicate, to, matcher|
18
+ msg = message_inflected(predicate)
19
+ add_offense(node, message: msg) do |corrector|
20
+ remove_predicate(corrector, predicate)
21
+ corrector.replace(node.loc.selector,
22
+ true?(to, matcher) ? 'to' : 'not_to')
23
+ rewrite_matcher(corrector, predicate, matcher)
24
+ end
22
25
  end
23
26
  end
24
27
 
@@ -76,17 +79,6 @@ module RuboCop
76
79
  end
77
80
  # rubocop:enable Metrics/MethodLength
78
81
 
79
- def autocorrect_inflected(node)
80
- predicate_in_actual?(node) do |predicate, to, matcher|
81
- lambda do |corrector|
82
- remove_predicate(corrector, predicate)
83
- corrector.replace(node.loc.selector,
84
- true?(to, matcher) ? 'to' : 'not_to')
85
- rewrite_matcher(corrector, predicate, matcher)
86
- end
87
- end
88
- end
89
-
90
82
  def remove_predicate(corrector, predicate)
91
83
  range = predicate.loc.dot.with(
92
84
  end_pos: predicate.loc.expression.end_pos
@@ -123,7 +115,6 @@ module RuboCop
123
115
  end
124
116
 
125
117
  # A helper for `explicit` style
126
- # rubocop:disable Metrics/ModuleLength
127
118
  module ExplicitHelper
128
119
  include RuboCop::RSpec::Language
129
120
  extend NodePattern::Macros
@@ -143,22 +134,21 @@ module RuboCop
143
134
  end
144
135
 
145
136
  def check_explicit(node) # rubocop:disable Metrics/MethodLength
146
- predicate_matcher_block?(node) do |_actual, matcher|
147
- add_offense(
148
- node,
149
- message: message_explicit(matcher)
150
- )
137
+ predicate_matcher_block?(node) do |actual, matcher|
138
+ add_offense(node, message: message_explicit(matcher)) do |corrector|
139
+ to_node = node.send_node
140
+ corrector_explicit(corrector, to_node, actual, matcher, to_node)
141
+ end
151
142
  ignore_node(node.children.first)
152
143
  return
153
144
  end
154
145
 
155
146
  return if part_of_ignored_node?(node)
156
147
 
157
- predicate_matcher?(node) do |_actual, matcher|
158
- add_offense(
159
- node,
160
- message: message_explicit(matcher)
161
- )
148
+ predicate_matcher?(node) do |actual, matcher|
149
+ add_offense(node, message: message_explicit(matcher)) do |corrector|
150
+ corrector_explicit(corrector, node, actual, matcher, matcher)
151
+ end
162
152
  end
163
153
  end
164
154
 
@@ -193,31 +183,11 @@ module RuboCop
193
183
  matcher_name: matcher.method_name)
194
184
  end
195
185
 
196
- def autocorrect_explicit(node)
197
- autocorrect_explicit_send(node) ||
198
- autocorrect_explicit_block(node)
199
- end
200
-
201
- def autocorrect_explicit_send(node)
202
- predicate_matcher?(node) do |actual, matcher|
203
- corrector_explicit(node, actual, matcher, matcher)
204
- end
205
- end
206
-
207
- def autocorrect_explicit_block(node)
208
- predicate_matcher_block?(node) do |actual, matcher|
209
- to_node = node.send_node
210
- corrector_explicit(to_node, actual, matcher, to_node)
211
- end
212
- end
213
-
214
- def corrector_explicit(to_node, actual, matcher, block_child)
215
- lambda do |corrector|
216
- replacement_matcher = replacement_matcher(to_node)
217
- corrector.replace(matcher.loc.expression, replacement_matcher)
218
- move_predicate(corrector, actual, matcher, block_child)
219
- corrector.replace(to_node.loc.selector, 'to')
220
- end
186
+ def corrector_explicit(corrector, to_node, actual, matcher, block_child)
187
+ replacement_matcher = replacement_matcher(to_node)
188
+ corrector.replace(matcher.loc.expression, replacement_matcher)
189
+ move_predicate(corrector, actual, matcher, block_child)
190
+ corrector.replace(to_node.loc.selector, 'to')
221
191
  end
222
192
 
223
193
  def move_predicate(corrector, actual, matcher, block_child)
@@ -261,7 +231,6 @@ module RuboCop
261
231
  end
262
232
  end
263
233
  end
264
- # rubocop:enable Metrics/ModuleLength
265
234
 
266
235
  # Prefer using predicate matcher over using predicate method directly.
267
236
  #
@@ -301,6 +270,7 @@ module RuboCop
301
270
  # # good - the above code is rewritten to it by this cop
302
271
  # expect(foo.something?).to be_truthy
303
272
  class PredicateMatcher < Cop
273
+ extend AutoCorrector
304
274
  include ConfigurableEnforcedStyle
305
275
  include InflectedHelper
306
276
  include ExplicitHelper