rubocop-rspec 1.41.0 → 1.42.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.
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
@@ -34,6 +34,7 @@ module RuboCop
34
34
  # it { does_something }
35
35
  #
36
36
  class EmptyLineAfterHook < Cop
37
+ extend AutoCorrector
37
38
  include RuboCop::RSpec::BlankLineSeparation
38
39
 
39
40
  MSG = 'Add an empty line after `%<hook>s`.'
@@ -43,11 +44,10 @@ module RuboCop
43
44
  return if last_child?(node)
44
45
 
45
46
  missing_separating_line(node) do |location|
46
- add_offense(
47
- node,
48
- location: location,
49
- message: format(MSG, hook: node.method_name)
50
- )
47
+ msg = format(MSG, hook: node.method_name)
48
+ add_offense(location, message: msg) do |corrector|
49
+ corrector.insert_after(location.end, "\n")
50
+ end
51
51
  end
52
52
  end
53
53
  end
@@ -15,6 +15,7 @@ module RuboCop
15
15
  #
16
16
  # let(:foo) { bar }
17
17
  class EmptyLineAfterSubject < Cop
18
+ extend AutoCorrector
18
19
  include RuboCop::RSpec::BlankLineSeparation
19
20
 
20
21
  MSG = 'Add empty line after `subject`.'
@@ -24,7 +25,9 @@ module RuboCop
24
25
  return if last_child?(node)
25
26
 
26
27
  missing_separating_line(node) do |location|
27
- add_offense(node, location: location)
28
+ add_offense(location) do |corrector|
29
+ corrector.insert_after(location.end, "\n")
30
+ end
28
31
  end
29
32
  end
30
33
 
@@ -30,6 +30,8 @@ module RuboCop
30
30
  # it 'does things' do
31
31
  # end
32
32
  class ExampleWording < Cop
33
+ extend AutoCorrector
34
+
33
35
  MSG_SHOULD = 'Do not use should when describing your tests.'
34
36
  MSG_IT = "Do not repeat 'it' when describing your tests."
35
37
 
@@ -53,16 +55,13 @@ module RuboCop
53
55
  end
54
56
  end
55
57
 
56
- def autocorrect(node)
57
- lambda do |corrector|
58
- corrector.replace(docstring(node), replacement_text(node))
59
- end
60
- end
61
-
62
58
  private
63
59
 
64
60
  def add_wording_offense(node, message)
65
- add_offense(node, location: docstring(node), message: message)
61
+ docstring = docstring(node)
62
+ add_offense(docstring, message: message) do |corrector|
63
+ corrector.replace(docstring, replacement_text(node))
64
+ end
66
65
  end
67
66
 
68
67
  def docstring(node)
@@ -17,6 +17,8 @@ module RuboCop
17
17
  # expect(name).to eq("John")
18
18
  #
19
19
  class ExpectActual < Cop
20
+ extend AutoCorrector
21
+
20
22
  MSG = 'Provide the actual you are testing to `expect(...)`.'
21
23
 
22
24
  SIMPLE_LITERALS = %i[
@@ -55,17 +57,12 @@ module RuboCop
55
57
  PATTERN
56
58
 
57
59
  def on_send(node)
58
- expect_literal(node) do |argument|
59
- add_offense(node, location: argument.source_range)
60
- end
61
- end
62
-
63
- def autocorrect(node)
64
- actual, matcher, expected = expect_literal(node)
65
- lambda do |corrector|
66
- return unless SUPPORTED_MATCHERS.include?(matcher)
60
+ expect_literal(node) do |actual, matcher, expected|
61
+ add_offense(actual.source_range) do |corrector|
62
+ next unless SUPPORTED_MATCHERS.include?(matcher)
67
63
 
68
- swap(corrector, actual, expected)
64
+ swap(corrector, actual, expected)
65
+ end
69
66
  end
70
67
  end
71
68
 
@@ -30,6 +30,7 @@ module RuboCop
30
30
  # expect { run }.to change { user.reload.name }
31
31
  #
32
32
  class ExpectChange < Cop
33
+ extend AutoCorrector
33
34
  include ConfigurableEnforcedStyle
34
35
 
35
36
  MSG_BLOCK = 'Prefer `change(%<obj>s, :%<attr>s)`.'
@@ -51,10 +52,11 @@ module RuboCop
51
52
  return unless style == :block
52
53
 
53
54
  expect_change_with_arguments(node) do |receiver, message|
54
- add_offense(
55
- node,
56
- message: format(MSG_CALL, obj: receiver, attr: message)
57
- )
55
+ msg = format(MSG_CALL, obj: receiver, attr: message)
56
+ add_offense(node, message: msg) do |corrector|
57
+ replacement = "change { #{receiver}.#{message} }"
58
+ corrector.replace(node, replacement)
59
+ end
58
60
  end
59
61
  end
60
62
 
@@ -62,37 +64,10 @@ module RuboCop
62
64
  return unless style == :method_call
63
65
 
64
66
  expect_change_with_block(node) do |receiver, message|
65
- add_offense(
66
- node,
67
- message: format(MSG_BLOCK, obj: receiver, attr: message)
68
- )
69
- end
70
- end
71
-
72
- def autocorrect(node)
73
- if style == :block
74
- autocorrect_method_call_to_block(node)
75
- else
76
- autocorrect_block_to_method_call(node)
77
- end
78
- end
79
-
80
- private
81
-
82
- def autocorrect_method_call_to_block(node)
83
- lambda do |corrector|
84
- expect_change_with_arguments(node) do |receiver, message|
85
- replacement = "change { #{receiver}.#{message} }"
86
- corrector.replace(node.loc.expression, replacement)
87
- end
88
- end
89
- end
90
-
91
- def autocorrect_block_to_method_call(node)
92
- lambda do |corrector|
93
- expect_change_with_block(node) do |receiver, message|
67
+ msg = format(MSG_BLOCK, obj: receiver, attr: message)
68
+ add_offense(node, message: msg) do |corrector|
94
69
  replacement = "change(#{receiver}, :#{message})"
95
- corrector.replace(node.loc.expression, replacement)
70
+ corrector.replace(node, replacement)
96
71
  end
97
72
  end
98
73
  end
@@ -30,8 +30,8 @@ module RuboCop
30
30
  return if node.body.nil?
31
31
 
32
32
  expectation(node.body) do |expect|
33
- add_offense(expect, location: :selector,
34
- message: message(expect, node))
33
+ add_offense(expect.loc.selector,
34
+ message: message(expect, node))
35
35
  end
36
36
  end
37
37
 
@@ -27,7 +27,7 @@ module RuboCop
27
27
  name = variable_name[1..-1]
28
28
  return unless name.eql?('stdout') || name.eql?('stderr')
29
29
 
30
- add_offense(node, location: :name, message: format(MSG, name: name))
30
+ add_offense(node.loc.name, message: format(MSG, name: name))
31
31
  end
32
32
 
33
33
  private
@@ -25,6 +25,8 @@ module RuboCop
25
25
  # # good
26
26
  # count { 1 }
27
27
  class AttributeDefinedStatically < Cop
28
+ extend AutoCorrector
29
+
28
30
  MSG = 'Use a block to declare attribute values.'
29
31
 
30
32
  def_node_matcher :value_matcher, <<-PATTERN
@@ -43,20 +45,22 @@ module RuboCop
43
45
  next unless offensive_receiver?(attribute.receiver, node)
44
46
  next if proc?(attribute) || association?(attribute.first_argument)
45
47
 
46
- add_offense(attribute)
48
+ add_offense(attribute) do |corrector|
49
+ autocorrect(corrector, attribute)
50
+ end
47
51
  end
48
52
  end
49
53
 
50
- def autocorrect(node)
54
+ private
55
+
56
+ def autocorrect(corrector, node)
51
57
  if node.parenthesized?
52
- autocorrect_replacing_parens(node)
58
+ autocorrect_replacing_parens(corrector, node)
53
59
  else
54
- autocorrect_without_parens(node)
60
+ autocorrect_without_parens(corrector, node)
55
61
  end
56
62
  end
57
63
 
58
- private
59
-
60
64
  def offensive_receiver?(receiver, node)
61
65
  receiver.nil? ||
62
66
  receiver.self_type? ||
@@ -77,24 +81,20 @@ module RuboCop
77
81
 
78
82
  def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
79
83
 
80
- def autocorrect_replacing_parens(node)
84
+ def autocorrect_replacing_parens(corrector, node)
81
85
  left_braces, right_braces = braces(node)
82
86
 
83
- lambda do |corrector|
84
- corrector.replace(node.location.begin, ' ' + left_braces)
85
- corrector.replace(node.location.end, right_braces)
86
- end
87
+ corrector.replace(node.location.begin, ' ' + left_braces)
88
+ corrector.replace(node.location.end, right_braces)
87
89
  end
88
90
 
89
- def autocorrect_without_parens(node)
91
+ def autocorrect_without_parens(corrector, node)
90
92
  left_braces, right_braces = braces(node)
91
93
 
92
- lambda do |corrector|
93
- argument = node.first_argument
94
- expression = argument.location.expression
95
- corrector.insert_before(expression, left_braces)
96
- corrector.insert_after(expression, right_braces)
97
- end
94
+ argument = node.first_argument
95
+ expression = argument.location.expression
96
+ corrector.insert_before(expression, left_braces)
97
+ corrector.insert_after(expression, right_braces)
98
98
  end
99
99
 
100
100
  def braces(node)
@@ -25,6 +25,7 @@ module RuboCop
25
25
  # # good
26
26
  # 3.times { create :user }
27
27
  class CreateList < Cop
28
+ extend AutoCorrector
28
29
  include ConfigurableEnforcedStyle
29
30
 
30
31
  MSG_CREATE_LIST = 'Prefer create_list.'
@@ -51,26 +52,19 @@ module RuboCop
51
52
  return unless n_times_block_without_arg?(node)
52
53
  return unless contains_only_factory?(node.body)
53
54
 
54
- add_offense(node.send_node, message: MSG_CREATE_LIST)
55
+ add_offense(node.send_node, message: MSG_CREATE_LIST) do |corrector|
56
+ CreateListCorrector.new(node.send_node).call(corrector)
57
+ end
55
58
  end
56
59
 
57
60
  def on_send(node)
58
61
  return unless style == :n_times
59
62
 
60
63
  factory_list_call(node) do |_receiver, _factory, count, _|
61
- add_offense(
62
- node,
63
- location: :selector,
64
- message: format(MSG_N_TIMES, number: count)
65
- )
66
- end
67
- end
68
-
69
- def autocorrect(node)
70
- if style == :create_list
71
- CreateListCorrector.new(node)
72
- else
73
- TimesCorrector.new(node)
64
+ message = format(MSG_N_TIMES, number: count)
65
+ add_offense(node.loc.selector, message: message) do |corrector|
66
+ TimesCorrector.new(node).call(corrector)
67
+ end
74
68
  end
75
69
  end
76
70
 
@@ -115,7 +109,7 @@ module RuboCop
115
109
 
116
110
  def call(corrector)
117
111
  replacement = generate_n_times_block(node)
118
- corrector.replace(node.loc.expression, replacement)
112
+ corrector.replace(node, replacement)
119
113
  end
120
114
 
121
115
  private
@@ -148,7 +142,7 @@ module RuboCop
148
142
  call_replacement(node)
149
143
  end
150
144
 
151
- corrector.replace(node.loc.expression, replacement)
145
+ corrector.replace(node, replacement)
152
146
  end
153
147
 
154
148
  private
@@ -20,6 +20,8 @@ module RuboCop
20
20
  # factory :foo, class: 'Foo' do
21
21
  # end
22
22
  class FactoryClassName < Cop
23
+ extend AutoCorrector
24
+
23
25
  MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
24
26
  'constant.'
25
27
  ALLOWED_CONSTANTS = %w[Hash OpenStruct].freeze
@@ -32,13 +34,10 @@ module RuboCop
32
34
  class_name(node) do |cn|
33
35
  next if allowed?(cn.const_name)
34
36
 
35
- add_offense(cn, message: format(MSG, class_name: cn.const_name))
36
- end
37
- end
38
-
39
- def autocorrect(node)
40
- lambda do |corrector|
41
- corrector.replace(node.loc.expression, "'#{node.source}'")
37
+ msg = format(MSG, class_name: cn.const_name)
38
+ add_offense(cn, message: msg) do |corrector|
39
+ corrector.replace(cn, "'#{cn.source}'")
40
+ end
42
41
  end
43
42
  end
44
43
 
@@ -58,6 +58,7 @@ module RuboCop
58
58
  # # ...
59
59
  # end
60
60
  class HookArgument < Cop
61
+ extend AutoCorrector
61
62
  include ConfigurableEnforcedStyle
62
63
 
63
64
  IMPLICIT_MSG = 'Omit the default `%<scope>p` ' \
@@ -78,18 +79,11 @@ module RuboCop
78
79
  return check_implicit(method_send) unless scope_name
79
80
 
80
81
  style_detected(scope_name)
81
- add_offense(
82
- method_send,
83
- message: explicit_message(scope_name)
84
- )
85
- end
86
- end
87
-
88
- def autocorrect(node)
89
- scope = implicit_style? ? '' : "(#{style.inspect})"
90
-
91
- lambda do |corrector|
92
- corrector.replace(argument_range(node), scope)
82
+ msg = explicit_message(scope_name)
83
+ add_offense(method_send, message: msg) do |corrector|
84
+ scope = implicit_style? ? '' : "(#{style.inspect})"
85
+ corrector.replace(argument_range(method_send), scope)
86
+ end
93
87
  end
94
88
  end
95
89
 
@@ -99,11 +93,11 @@ module RuboCop
99
93
  style_detected(:implicit)
100
94
  return if implicit_style?
101
95
 
102
- add_offense(
103
- method_send,
104
- location: :selector,
105
- message: format(EXPLICIT_MSG, scope: style)
106
- )
96
+ msg = explicit_message(nil)
97
+ add_offense(method_send.loc.selector, message: msg) do |corrector|
98
+ scope = "(#{style.inspect})"
99
+ corrector.replace(argument_range(method_send), scope)
100
+ end
107
101
  end
108
102
 
109
103
  def explicit_message(scope)
@@ -24,6 +24,8 @@ module RuboCop
24
24
  # end
25
25
  #
26
26
  class HooksBeforeExamples < Cop
27
+ extend AutoCorrector
28
+
27
29
  MSG = 'Move `%<hook>s` above the examples in the group.'
28
30
 
29
31
  def_node_matcher :example_or_group?, <<-PATTERN
@@ -39,15 +41,6 @@ module RuboCop
39
41
  check_hooks(node.body) if multiline_block?(node.body)
40
42
  end
41
43
 
42
- def autocorrect(node)
43
- lambda do |corrector|
44
- first_example = find_first_example(node.parent)
45
- RuboCop::RSpec::Corrector::MoveNode.new(
46
- node, corrector, processed_source
47
- ).move_before(first_example)
48
- end
49
- end
50
-
51
44
  private
52
45
 
53
46
  def multiline_block?(block)
@@ -62,16 +55,22 @@ module RuboCop
62
55
  next if child.sibling_index < first_example.sibling_index
63
56
  next unless hook?(child)
64
57
 
65
- add_offense(
66
- child,
67
- message: format(MSG, hook: child.method_name)
68
- )
58
+ msg = format(MSG, hook: child.method_name)
59
+ add_offense(child, message: msg) do |corrector|
60
+ autocorrect(corrector, child, first_example)
61
+ end
69
62
  end
70
63
  end
71
64
 
72
65
  def find_first_example(node)
73
66
  node.children.find { |sibling| example_or_group?(sibling) }
74
67
  end
68
+
69
+ def autocorrect(corrector, node, first_example)
70
+ RuboCop::RSpec::Corrector::MoveNode.new(
71
+ node, corrector, processed_source
72
+ ).move_before(first_example)
73
+ end
75
74
  end
76
75
  end
77
76
  end