rubocop-rspec 1.44.1 → 2.2.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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -1
  3. data/README.md +5 -1
  4. data/config/default.yml +171 -81
  5. data/lib/rubocop-rspec.rb +8 -8
  6. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +7 -3
  7. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +7 -3
  8. data/lib/rubocop/cop/rspec/any_instance.rb +6 -10
  9. data/lib/rubocop/cop/rspec/around_block.rb +1 -1
  10. data/lib/rubocop/cop/rspec/base.rb +6 -55
  11. data/lib/rubocop/cop/rspec/be.rb +2 -2
  12. data/lib/rubocop/cop/rspec/be_eql.rb +1 -0
  13. data/lib/rubocop/cop/rspec/before_after_all.rb +5 -3
  14. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +4 -2
  15. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +3 -2
  16. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +2 -0
  17. data/lib/rubocop/cop/rspec/describe_class.rb +2 -2
  18. data/lib/rubocop/cop/rspec/describe_method.rb +2 -2
  19. data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -0
  20. data/lib/rubocop/cop/rspec/described_class.rb +1 -2
  21. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -2
  22. data/lib/rubocop/cop/rspec/dialect.rb +1 -1
  23. data/lib/rubocop/cop/rspec/empty_example_group.rb +6 -45
  24. data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
  25. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +1 -1
  26. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
  27. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +1 -1
  28. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +1 -1
  29. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +2 -2
  30. data/lib/rubocop/cop/rspec/expect_actual.rb +2 -1
  31. data/lib/rubocop/cop/rspec/expect_change.rb +1 -0
  32. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  33. data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
  34. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +1 -0
  35. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -0
  36. data/lib/rubocop/cop/rspec/file_path.rb +24 -17
  37. data/lib/rubocop/cop/rspec/focus.rb +43 -8
  38. data/lib/rubocop/cop/rspec/hook_argument.rb +2 -4
  39. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +2 -2
  40. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -0
  41. data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
  42. data/lib/rubocop/cop/rspec/implicit_subject.rb +1 -0
  43. data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
  44. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  45. data/lib/rubocop/cop/rspec/it_behaves_like.rb +2 -1
  46. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  47. data/lib/rubocop/cop/rspec/let_before_examples.rb +2 -2
  48. data/lib/rubocop/cop/rspec/let_setup.rb +7 -4
  49. data/lib/rubocop/cop/rspec/message_chain.rb +4 -10
  50. data/lib/rubocop/cop/rspec/message_expectation.rb +1 -0
  51. data/lib/rubocop/cop/rspec/message_spies.rb +3 -3
  52. data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
  53. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +51 -0
  54. data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
  55. data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
  56. data/lib/rubocop/cop/rspec/mixin/variable.rb +20 -0
  57. data/lib/rubocop/cop/rspec/multiple_describes.rb +2 -3
  58. data/lib/rubocop/cop/rspec/multiple_expectations.rb +1 -1
  59. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +3 -1
  60. data/lib/rubocop/cop/rspec/named_subject.rb +8 -12
  61. data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
  62. data/lib/rubocop/cop/rspec/not_to_not.rb +1 -0
  63. data/lib/rubocop/cop/rspec/overwriting_setup.rb +2 -1
  64. data/lib/rubocop/cop/rspec/pending.rb +13 -5
  65. data/lib/rubocop/cop/rspec/predicate_matcher.rb +3 -3
  66. data/lib/rubocop/cop/rspec/rails/http_status.rb +1 -0
  67. data/lib/rubocop/cop/rspec/receive_counts.rb +2 -0
  68. data/lib/rubocop/cop/rspec/receive_never.rb +1 -0
  69. data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -2
  70. data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -0
  71. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  72. data/lib/rubocop/cop/rspec/shared_context.rb +18 -11
  73. data/lib/rubocop/cop/rspec/shared_examples.rb +3 -1
  74. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +2 -1
  75. data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
  76. data/lib/rubocop/cop/rspec/subject_stub.rb +16 -6
  77. data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -0
  78. data/lib/rubocop/cop/rspec/variable_definition.rb +1 -1
  79. data/lib/rubocop/cop/rspec/variable_name.rb +1 -1
  80. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -0
  81. data/lib/rubocop/cop/rspec/void_expect.rb +1 -0
  82. data/lib/rubocop/cop/rspec_cops.rb +0 -1
  83. data/lib/rubocop/rspec/align_let_brace.rb +1 -1
  84. data/lib/rubocop/rspec/concept.rb +2 -2
  85. data/lib/rubocop/rspec/config_formatter.rb +5 -3
  86. data/lib/rubocop/rspec/corrector/move_node.rb +7 -10
  87. data/lib/rubocop/rspec/example_group.rb +15 -5
  88. data/lib/rubocop/rspec/hook.rb +1 -1
  89. data/lib/rubocop/rspec/inject.rb +4 -2
  90. data/lib/rubocop/rspec/language.rb +143 -109
  91. data/lib/rubocop/rspec/language/node_pattern.rb +7 -24
  92. data/lib/rubocop/rspec/node.rb +1 -1
  93. data/lib/rubocop/rspec/version.rb +1 -1
  94. metadata +12 -15
  95. data/lib/rubocop/cop/rspec/cop.rb +0 -10
  96. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +0 -41
  97. data/lib/rubocop/rspec.rb +0 -12
  98. data/lib/rubocop/rspec/empty_line_separation.rb +0 -48
  99. data/lib/rubocop/rspec/final_end_location.rb +0 -17
  100. data/lib/rubocop/rspec/top_level_describe.rb +0 -52
  101. data/lib/rubocop/rspec/top_level_group.rb +0 -57
  102. data/lib/rubocop/rspec/variable.rb +0 -16
@@ -29,7 +29,7 @@ module RuboCop
29
29
  MSG = 'Empty hook detected.'
30
30
 
31
31
  def_node_matcher :empty_hook?, <<~PATTERN
32
- (block $#{Hooks::ALL.send_pattern} _ nil?)
32
+ (block $#{send_pattern('#Hooks.all')} _ nil?)
33
33
  PATTERN
34
34
 
35
35
  def on_block(node)
@@ -43,7 +43,7 @@ module RuboCop
43
43
  #
44
44
  class EmptyLineAfterExample < Base
45
45
  extend AutoCorrector
46
- include RuboCop::RSpec::EmptyLineSeparation
46
+ include EmptyLineSeparation
47
47
 
48
48
  MSG = 'Add an empty line after `%<example>s`.'
49
49
 
@@ -25,7 +25,7 @@ module RuboCop
25
25
  #
26
26
  class EmptyLineAfterExampleGroup < Base
27
27
  extend AutoCorrector
28
- include RuboCop::RSpec::EmptyLineSeparation
28
+ include EmptyLineSeparation
29
29
 
30
30
  MSG = 'Add an empty line after `%<example_group>s`.'
31
31
 
@@ -18,7 +18,7 @@ module RuboCop
18
18
  # it { does_something }
19
19
  class EmptyLineAfterFinalLet < Base
20
20
  extend AutoCorrector
21
- include RuboCop::RSpec::EmptyLineSeparation
21
+ include EmptyLineSeparation
22
22
 
23
23
  MSG = 'Add an empty line after the last `%<let>s`.'
24
24
 
@@ -35,7 +35,7 @@ module RuboCop
35
35
  #
36
36
  class EmptyLineAfterHook < Base
37
37
  extend AutoCorrector
38
- include RuboCop::RSpec::EmptyLineSeparation
38
+ include EmptyLineSeparation
39
39
 
40
40
  MSG = 'Add an empty line after `%<hook>s`.'
41
41
 
@@ -16,7 +16,7 @@ module RuboCop
16
16
  # let(:foo) { bar }
17
17
  class EmptyLineAfterSubject < Base
18
18
  extend AutoCorrector
19
- include RuboCop::RSpec::EmptyLineSeparation
19
+ include EmptyLineSeparation
20
20
 
21
21
  MSG = 'Add an empty line after `%<subject>s`.'
22
22
 
@@ -32,7 +32,7 @@ module RuboCop
32
32
 
33
33
  def in_spec_block?(node)
34
34
  node.each_ancestor(:block).any? do |ancestor|
35
- Examples::ALL.include?(ancestor.method_name)
35
+ Examples.all(ancestor.method_name)
36
36
  end
37
37
  end
38
38
  end
@@ -48,7 +48,7 @@ module RuboCop
48
48
  def_node_matcher :expect_literal, <<~PATTERN
49
49
  (send
50
50
  (send nil? :expect $#literal?)
51
- #{Runners::ALL.node_pattern_union}
51
+ #Runners.all
52
52
  {
53
53
  (send (send nil? $:be) :== $_)
54
54
  (send nil? $_ $_ ...)
@@ -60,6 +60,7 @@ module RuboCop
60
60
  expect_literal(node) do |actual, matcher, expected|
61
61
  add_offense(actual.source_range) do |corrector|
62
62
  next unless SUPPORTED_MATCHERS.include?(matcher)
63
+ next if literal?(expected)
63
64
 
64
65
  swap(corrector, actual, expected)
65
66
  end
@@ -35,6 +35,7 @@ module RuboCop
35
35
 
36
36
  MSG_BLOCK = 'Prefer `change(%<obj>s, :%<attr>s)`.'
37
37
  MSG_CALL = 'Prefer `change { %<obj>s.%<attr>s }`.'
38
+ RESTRICT_ON_SEND = %i[change].freeze
38
39
 
39
40
  def_node_matcher :expect_change_with_arguments, <<-PATTERN
40
41
  (send nil? :change ({const send} nil? $_) (sym $_))
@@ -23,7 +23,7 @@ module RuboCop
23
23
  class ExpectInHook < Base
24
24
  MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
25
25
 
26
- def_node_search :expectation, Expectations::ALL.send_pattern
26
+ def_node_search :expectation, send_pattern('#Expectations.all')
27
27
 
28
28
  def on_block(node)
29
29
  return unless hook?(node)
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # # good
16
16
  # expect { my_app.print_report }.to output('Hello World').to_stdout
17
17
  class ExpectOutput < Base
18
- MSG = 'Use `expect { ... }.to output(...).to_%<name>s` '\
18
+ MSG = 'Use `expect { ... }.to output(...).to_%<name>s` ' \
19
19
  'instead of mutating $%<name>s.'
20
20
 
21
21
  def on_gvasgn(node)
@@ -30,6 +30,7 @@ module RuboCop
30
30
 
31
31
  MSG_CREATE_LIST = 'Prefer create_list.'
32
32
  MSG_N_TIMES = 'Prefer %<number>s.times.'
33
+ RESTRICT_ON_SEND = %i[create_list].freeze
33
34
 
34
35
  def_node_matcher :n_times_block_without_arg?, <<-PATTERN
35
36
  (block
@@ -25,6 +25,7 @@ module RuboCop
25
25
  MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
26
26
  'constant.'
27
27
  ALLOWED_CONSTANTS = %w[Hash OpenStruct].freeze
28
+ RESTRICT_ON_SEND = %i[factory].freeze
28
29
 
29
30
  def_node_matcher :class_name, <<~PATTERN
30
31
  (send _ :factory _ (hash <(pair (sym :class) $(const ...)) ...>))
@@ -57,7 +57,7 @@ module RuboCop
57
57
  # my_class_spec.rb # describe MyClass, '#method'
58
58
  #
59
59
  class FilePath < Base
60
- include RuboCop::RSpec::TopLevelGroup
60
+ include TopLevelGroup
61
61
 
62
62
  MSG = 'Spec path should end with `%<suffix>s`.'
63
63
 
@@ -82,30 +82,39 @@ module RuboCop
82
82
  private
83
83
 
84
84
  def ensure_correct_file_path(send_node, described_class, arguments)
85
- glob = glob_for(described_class, arguments.first)
86
- return if filename_ends_with?(glob)
87
-
88
- add_offense(send_node, message: format(MSG, suffix: glob))
85
+ pattern = pattern_for(described_class, arguments.first)
86
+ return if filename_ends_with?(pattern)
87
+
88
+ # For the suffix shown in the offense message, modify the regular
89
+ # expression pattern to resemble a glob pattern for clearer error
90
+ # messages.
91
+ offense_suffix = pattern.gsub('.*', '*').sub('[^/]', '')
92
+ .sub('\.', '.')
93
+ add_offense(send_node, message: format(MSG, suffix: offense_suffix))
89
94
  end
90
95
 
91
96
  def routing_spec?(args)
92
97
  args.any?(&method(:routing_metadata?))
93
98
  end
94
99
 
95
- def glob_for(described_class, method_name)
96
- return glob_for_spec_suffix_only? if spec_suffix_only?
100
+ def pattern_for(described_class, method_name)
101
+ return pattern_for_spec_suffix_only? if spec_suffix_only?
97
102
 
98
- "#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
103
+ [
104
+ expected_path(described_class),
105
+ name_pattern(method_name),
106
+ '[^/]*_spec\.rb'
107
+ ].join
99
108
  end
100
109
 
101
- def glob_for_spec_suffix_only?
102
- '*_spec.rb'
110
+ def pattern_for_spec_suffix_only?
111
+ '.*_spec\.rb'
103
112
  end
104
113
 
105
- def name_glob(method_name)
114
+ def name_pattern(method_name)
106
115
  return unless method_name&.str_type?
107
116
 
108
- "*#{method_name.str_content.gsub(/\W/, '')}" unless ignore_methods?
117
+ ".*#{method_name.str_content.gsub(/\W/, '')}" unless ignore_methods?
109
118
  end
110
119
 
111
120
  def expected_path(constant)
@@ -131,11 +140,9 @@ module RuboCop
131
140
  cop_config['IgnoreMethods']
132
141
  end
133
142
 
134
- def filename_ends_with?(glob)
135
- filename =
136
- RuboCop::PathUtil.relative_path(processed_source.buffer.name)
137
- .gsub('../', '')
138
- File.fnmatch?("*#{glob}", filename)
143
+ def filename_ends_with?(pattern)
144
+ filename = File.expand_path(processed_source.buffer.name)
145
+ filename.match?("#{pattern}$")
139
146
  end
140
147
 
141
148
  def relevant_rubocop_rspec_file?(_file)
@@ -20,25 +20,40 @@ module RuboCop
20
20
  # describe MyClass do
21
21
  # end
22
22
  class Focus < Base
23
- MSG = 'Focused spec found.'
23
+ extend AutoCorrector
24
+ include RangeHelp
24
25
 
25
- focused = ExampleGroups::FOCUSED + Examples::FOCUSED
26
+ MSG = 'Focused spec found.'
26
27
 
27
- def_node_matcher :focusable_selector?,
28
- (ExampleGroups::GROUPS + ExampleGroups::SKIPPED +
29
- Examples::EXAMPLES + Examples::SKIPPED +
30
- Examples::PENDING).node_pattern_union
28
+ def_node_matcher :focusable_selector?, <<-PATTERN
29
+ {
30
+ #ExampleGroups.regular
31
+ #ExampleGroups.skipped
32
+ #Examples.regular
33
+ #Examples.skipped
34
+ #Examples.pending
35
+ }
36
+ PATTERN
31
37
 
32
38
  def_node_matcher :metadata, <<-PATTERN
33
39
  {(send #rspec? #focusable_selector? <$(sym :focus) ...>)
34
40
  (send #rspec? #focusable_selector? ... (hash <$(pair (sym :focus) true) ...>))}
35
41
  PATTERN
36
42
 
37
- def_node_matcher :focused_block?, focused.send_pattern
43
+ def_node_matcher :focused_block?,
44
+ send_pattern(<<~PATTERN)
45
+ {#ExampleGroups.focused #Examples.focused}
46
+ PATTERN
38
47
 
39
48
  def on_send(node)
40
49
  focus_metadata(node) do |focus|
41
- add_offense(focus)
50
+ add_offense(focus) do |corrector|
51
+ if focus.pair_type? || focus.str_type? || focus.sym_type?
52
+ corrector.remove(with_surrounding(focus))
53
+ elsif focus.send_type?
54
+ correct_send(corrector, focus)
55
+ end
56
+ end
42
57
  end
43
58
  end
44
59
 
@@ -49,6 +64,26 @@ module RuboCop
49
64
 
50
65
  metadata(node, &block)
51
66
  end
67
+
68
+ def with_surrounding(focus)
69
+ range_with_space = range_with_surrounding_space(
70
+ range: focus.loc.expression,
71
+ side: :left
72
+ )
73
+
74
+ range_with_surrounding_comma(range_with_space, :left)
75
+ end
76
+
77
+ def correct_send(corrector, focus)
78
+ range = focus.loc.selector
79
+ unfocused = focus.method_name.to_s.sub(/^f/, '')
80
+ unless Examples.regular(unfocused) || ExampleGroups.regular(unfocused)
81
+ return
82
+ end
83
+
84
+ corrector.replace(range,
85
+ range.source.sub(focus.method_name.to_s, unfocused))
86
+ end
52
87
  end
53
88
  end
54
89
  end
@@ -64,13 +64,11 @@ module RuboCop
64
64
  IMPLICIT_MSG = 'Omit the default `%<scope>p` argument for RSpec hooks.'
65
65
  EXPLICIT_MSG = 'Use `%<scope>p` for RSpec hooks.'
66
66
 
67
- def_node_matcher :hook?, Hooks::ALL.node_pattern_union
68
-
69
67
  def_node_matcher :scoped_hook, <<-PATTERN
70
- (block $(send _ #hook? (sym ${:each :example})) ...)
68
+ (block $(send _ #Hooks.all (sym ${:each :example})) ...)
71
69
  PATTERN
72
70
 
73
- def_node_matcher :unscoped_hook, '(block $(send _ #hook?) ...)'
71
+ def_node_matcher :unscoped_hook, '(block $(send _ #Hooks.all) ...)'
74
72
 
75
73
  def on_block(node)
76
74
  hook(node) do |method_send, scope_name|
@@ -30,8 +30,8 @@ module RuboCop
30
30
 
31
31
  def_node_matcher :example_or_group?, <<-PATTERN
32
32
  {
33
- #{(Examples::ALL + ExampleGroups::ALL).block_pattern}
34
- #{Includes::EXAMPLES.send_pattern}
33
+ #{block_pattern('{#ExampleGroups.all #Examples.all}')}
34
+ #{send_pattern('#Includes.examples')}
35
35
  }
36
36
  PATTERN
37
37
 
@@ -18,6 +18,7 @@ module RuboCop
18
18
  # end
19
19
  class ImplicitBlockExpectation < Base
20
20
  MSG = 'Avoid implicit block expectations.'
21
+ RESTRICT_ON_SEND = %i[is_expected should should_not].freeze
21
22
 
22
23
  def_node_matcher :lambda?, <<-PATTERN
23
24
  {
@@ -33,7 +33,7 @@ module RuboCop
33
33
  def_node_matcher :implicit_expect, <<-PATTERN
34
34
  {
35
35
  (send nil? ${:should :should_not} ...)
36
- (send (send nil? $:is_expected) #{Runners::ALL.node_pattern_union} ...)
36
+ (send (send nil? $:is_expected) #Runners.all ...)
37
37
  }
38
38
  PATTERN
39
39
 
@@ -31,6 +31,7 @@ module RuboCop
31
31
  include ConfigurableEnforcedStyle
32
32
 
33
33
  MSG = "Don't use implicit subject."
34
+ RESTRICT_ON_SEND = %i[is_expected should should_not].freeze
34
35
 
35
36
  def_node_matcher :implicit_subject?, <<-PATTERN
36
37
  (send nil? {:should :should_not :is_expected} ...)
@@ -21,7 +21,7 @@ module RuboCop
21
21
  class InstanceSpy < Base
22
22
  extend AutoCorrector
23
23
 
24
- MSG = 'Use `instance_spy` when you check your double '\
24
+ MSG = 'Use `instance_spy` when you check your double ' \
25
25
  'with `have_received`.'
26
26
 
27
27
  def_node_search :null_double, <<-PATTERN
@@ -47,7 +47,7 @@ module RuboCop
47
47
  # end
48
48
  #
49
49
  class InstanceVariable < Base
50
- include RuboCop::RSpec::TopLevelGroup
50
+ include TopLevelGroup
51
51
 
52
52
  MSG = 'Avoid instance variables – use let, ' \
53
53
  'a method call, or a local variable (if possible).'
@@ -22,8 +22,9 @@ module RuboCop
22
22
  extend AutoCorrector
23
23
  include ConfigurableEnforcedStyle
24
24
 
25
- MSG = 'Prefer `%<replacement>s` over `%<original>s` when including '\
25
+ MSG = 'Prefer `%<replacement>s` over `%<original>s` when including ' \
26
26
  'examples in a nested context.'
27
+ RESTRICT_ON_SEND = %i[it_behaves_like it_should_behave_like].freeze
27
28
 
28
29
  def_node_matcher :example_inclusion_offense, '(send _ % ...)'
29
30
 
@@ -17,7 +17,7 @@ module RuboCop
17
17
  # end
18
18
  class IteratedExpectation < Base
19
19
  MSG = 'Prefer using the `all` matcher instead ' \
20
- 'of iterating over an array.'
20
+ 'of iterating over an array.'
21
21
 
22
22
  def_node_matcher :each?, <<-PATTERN
23
23
  (block
@@ -37,8 +37,8 @@ module RuboCop
37
37
 
38
38
  def_node_matcher :example_or_group?, <<-PATTERN
39
39
  {
40
- #{(Examples::ALL + ExampleGroups::ALL).block_pattern}
41
- #{Includes::EXAMPLES.send_pattern}
40
+ #{block_pattern('{#ExampleGroups.all #Examples.all}')}
41
+ #{send_pattern('#Includes.examples')}
42
42
  }
43
43
  PATTERN
44
44
 
@@ -29,10 +29,13 @@ module RuboCop
29
29
  MSG = 'Do not use `let!` to setup objects not referenced in tests.'
30
30
 
31
31
  def_node_matcher :example_or_shared_group_or_including?,
32
- (
33
- ExampleGroups::ALL + SharedGroups::ALL +
34
- Includes::ALL
35
- ).block_pattern
32
+ block_pattern(<<~PATTERN)
33
+ {
34
+ #SharedGroups.all
35
+ #ExampleGroups.all
36
+ #Includes.all
37
+ }
38
+ PATTERN
36
39
 
37
40
  def_node_matcher :let_bang, <<-PATTERN
38
41
  {
@@ -15,18 +15,12 @@ module RuboCop
15
15
  #
16
16
  class MessageChain < Base
17
17
  MSG = 'Avoid stubbing using `%<method>s`.'
18
-
19
- def_node_matcher :message_chain, <<-PATTERN
20
- (send _ {:receive_message_chain :stub_chain} ...)
21
- PATTERN
18
+ RESTRICT_ON_SEND = %i[receive_message_chain stub_chain].freeze
22
19
 
23
20
  def on_send(node)
24
- message_chain(node) do
25
- add_offense(
26
- node.loc.selector,
27
- message: format(MSG, method: node.method_name)
28
- )
29
- end
21
+ add_offense(
22
+ node.loc.selector, message: format(MSG, method: node.method_name)
23
+ )
30
24
  end
31
25
  end
32
26
  end
@@ -30,6 +30,7 @@ module RuboCop
30
30
  MSG = 'Prefer `%<style>s` for setting message expectations.'
31
31
 
32
32
  SUPPORTED_STYLES = %w[allow expect].freeze
33
+ RESTRICT_ON_SEND = %i[to].freeze
33
34
 
34
35
  def_node_matcher :message_expectation, <<-PATTERN
35
36
  (send $(send nil? {:expect :allow} ...) :to #receive_message?)