rubocop-rspec 1.39.0 → 1.43.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/CODE_OF_CONDUCT.md +17 -0
  4. data/README.md +1 -61
  5. data/config/default.yml +148 -20
  6. data/lib/rubocop-rspec.rb +4 -1
  7. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +12 -19
  8. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +12 -19
  9. data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
  10. data/lib/rubocop/cop/rspec/around_block.rb +1 -1
  11. data/lib/rubocop/cop/rspec/base.rb +74 -0
  12. data/lib/rubocop/cop/rspec/be.rb +2 -2
  13. data/lib/rubocop/cop/rspec/be_eql.rb +6 -6
  14. data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
  15. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +19 -17
  16. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +14 -12
  17. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +27 -12
  18. data/lib/rubocop/cop/rspec/context_method.rb +7 -9
  19. data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
  20. data/lib/rubocop/cop/rspec/cop.rb +2 -86
  21. data/lib/rubocop/cop/rspec/describe_class.rb +20 -27
  22. data/lib/rubocop/cop/rspec/describe_method.rb +14 -6
  23. data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
  24. data/lib/rubocop/cop/rspec/described_class.rb +12 -9
  25. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
  26. data/lib/rubocop/cop/rspec/dialect.rb +5 -12
  27. data/lib/rubocop/cop/rspec/empty_example_group.rb +91 -7
  28. data/lib/rubocop/cop/rspec/empty_hook.rb +6 -10
  29. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +5 -7
  30. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +5 -9
  31. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +8 -8
  32. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +5 -9
  33. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +6 -6
  34. data/lib/rubocop/cop/rspec/example_length.rb +1 -1
  35. data/lib/rubocop/cop/rspec/example_without_description.rb +1 -1
  36. data/lib/rubocop/cop/rspec/example_wording.rb +10 -11
  37. data/lib/rubocop/cop/rspec/expect_actual.rb +8 -11
  38. data/lib/rubocop/cop/rspec/expect_change.rb +10 -35
  39. data/lib/rubocop/cop/rspec/expect_in_hook.rb +3 -3
  40. data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
  41. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +24 -21
  42. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +20 -22
  43. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +7 -8
  44. data/lib/rubocop/cop/rspec/file_path.rb +54 -20
  45. data/lib/rubocop/cop/rspec/focus.rb +7 -11
  46. data/lib/rubocop/cop/rspec/hook_argument.rb +16 -23
  47. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +13 -14
  48. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -1
  49. data/lib/rubocop/cop/rspec/implicit_expect.rb +7 -15
  50. data/lib/rubocop/cop/rspec/implicit_subject.rb +16 -11
  51. data/lib/rubocop/cop/rspec/instance_spy.rb +18 -12
  52. data/lib/rubocop/cop/rspec/instance_variable.rb +4 -8
  53. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +3 -6
  54. data/lib/rubocop/cop/rspec/it_behaves_like.rb +5 -6
  55. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  56. data/lib/rubocop/cop/rspec/leading_subject.rb +24 -21
  57. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +2 -5
  58. data/lib/rubocop/cop/rspec/let_before_examples.rb +13 -11
  59. data/lib/rubocop/cop/rspec/let_setup.rb +21 -6
  60. data/lib/rubocop/cop/rspec/message_chain.rb +7 -6
  61. data/lib/rubocop/cop/rspec/message_expectation.rb +2 -2
  62. data/lib/rubocop/cop/rspec/message_spies.rb +2 -3
  63. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -1
  64. data/lib/rubocop/cop/rspec/multiple_describes.rb +11 -8
  65. data/lib/rubocop/cop/rspec/multiple_expectations.rb +7 -11
  66. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +148 -0
  67. data/lib/rubocop/cop/rspec/multiple_subjects.rb +18 -19
  68. data/lib/rubocop/cop/rspec/named_subject.rb +2 -2
  69. data/lib/rubocop/cop/rspec/nested_groups.rb +12 -13
  70. data/lib/rubocop/cop/rspec/not_to_not.rb +5 -6
  71. data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
  72. data/lib/rubocop/cop/rspec/pending.rb +1 -1
  73. data/lib/rubocop/cop/rspec/predicate_matcher.rb +32 -69
  74. data/lib/rubocop/cop/rspec/rails/http_status.rb +7 -9
  75. data/lib/rubocop/cop/rspec/receive_counts.rb +15 -17
  76. data/lib/rubocop/cop/rspec/receive_never.rb +12 -12
  77. data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
  78. data/lib/rubocop/cop/rspec/repeated_example.rb +2 -2
  79. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +12 -2
  80. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
  81. data/lib/rubocop/cop/rspec/return_from_stub.rb +12 -22
  82. data/lib/rubocop/cop/rspec/scattered_let.rb +8 -11
  83. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  84. data/lib/rubocop/cop/rspec/shared_context.rb +8 -21
  85. data/lib/rubocop/cop/rspec/shared_examples.rb +7 -9
  86. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +15 -18
  87. data/lib/rubocop/cop/rspec/subject_stub.rb +25 -53
  88. data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
  89. data/lib/rubocop/cop/rspec/variable_definition.rb +56 -0
  90. data/lib/rubocop/cop/rspec/variable_name.rb +66 -0
  91. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
  92. data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
  93. data/lib/rubocop/cop/rspec/yield.rb +14 -11
  94. data/lib/rubocop/cop/rspec_cops.rb +3 -0
  95. data/lib/rubocop/rspec/corrector/move_node.rb +7 -5
  96. data/lib/rubocop/rspec/description_extractor.rb +2 -6
  97. data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -10
  98. data/lib/rubocop/rspec/example_group.rb +21 -49
  99. data/lib/rubocop/rspec/factory_bot.rb +7 -1
  100. data/lib/rubocop/rspec/language.rb +6 -4
  101. data/lib/rubocop/rspec/language/node_pattern.rb +10 -1
  102. data/lib/rubocop/rspec/top_level_describe.rb +2 -2
  103. data/lib/rubocop/rspec/top_level_group.rb +57 -0
  104. data/lib/rubocop/rspec/variable.rb +16 -0
  105. data/lib/rubocop/rspec/version.rb +1 -1
  106. metadata +32 -11
@@ -19,7 +19,7 @@ module RuboCop
19
19
  #
20
20
  # describe "A feature example" do
21
21
  # end
22
- class MissingExampleGroupArgument < Cop
22
+ class MissingExampleGroupArgument < Base
23
23
  MSG = 'The first argument to `%<method>s` should not be empty.'
24
24
 
25
25
  def on_block(node)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # Checks for multiple top level describes.
6
+ # Checks for multiple top-level example groups.
7
7
  #
8
8
  # Multiple descriptions for the same class or module should either
9
9
  # be nested or separated into different test files.
@@ -22,17 +22,20 @@ module RuboCop
22
22
  # describe '.do_something_else' do
23
23
  # end
24
24
  # end
25
- class MultipleDescribes < Cop
26
- include RuboCop::RSpec::TopLevelDescribe
25
+ class MultipleDescribes < Base
26
+ include RuboCop::RSpec::TopLevelGroup
27
27
 
28
- MSG = 'Do not use multiple top level describes - '\
28
+ MSG = 'Do not use multiple top-level example groups - '\
29
29
  'try to nest them.'
30
30
 
31
- def on_top_level_describe(node, _args)
32
- return if single_top_level_describe?
33
- return unless top_level_nodes.first.equal?(node)
31
+ def on_top_level_group(node)
32
+ top_level_example_groups =
33
+ top_level_groups.select(&method(:example_group?))
34
34
 
35
- add_offense(node)
35
+ return if top_level_example_groups.one?
36
+ return unless top_level_example_groups.first.equal?(node)
37
+
38
+ add_offense(node.send_node)
36
39
  end
37
40
  end
38
41
  end
@@ -45,22 +45,18 @@ module RuboCop
45
45
  # end
46
46
  # end
47
47
  #
48
- class MultipleExpectations < Cop
48
+ class MultipleExpectations < Base
49
49
  include ConfigurableMax
50
50
 
51
51
  MSG = 'Example has too many expectations [%<total>d/%<max>d].'
52
52
 
53
- def_node_matcher :aggregate_failures?, <<-PATTERN
54
- (block {
55
- (send _ _ <(sym :aggregate_failures) ...>)
56
- (send _ _ ... (hash <(pair (sym :aggregate_failures) true) ...>))
57
- } ...)
58
- PATTERN
53
+ ANYTHING = ->(_node) { true }
54
+ TRUE = ->(node) { node.true_type? }
59
55
 
60
- def_node_matcher :aggregate_failures_present?, <<-PATTERN
56
+ def_node_matcher :aggregate_failures?, <<-PATTERN
61
57
  (block {
62
58
  (send _ _ <(sym :aggregate_failures) ...>)
63
- (send _ _ ... (hash <(pair (sym :aggregate_failures) _) ...>))
59
+ (send _ _ ... (hash <(pair (sym :aggregate_failures) %1) ...>))
64
60
  } ...)
65
61
  PATTERN
66
62
 
@@ -89,12 +85,12 @@ module RuboCop
89
85
  node_with_aggregate_failures = find_aggregate_failures(example_node)
90
86
  return false unless node_with_aggregate_failures
91
87
 
92
- aggregate_failures?(node_with_aggregate_failures)
88
+ aggregate_failures?(node_with_aggregate_failures, TRUE)
93
89
  end
94
90
 
95
91
  def find_aggregate_failures(example_node)
96
92
  example_node.send_node.each_ancestor(:block)
97
- .find { |block_node| aggregate_failures_present?(block_node) }
93
+ .find { |block_node| aggregate_failures?(block_node, ANYTHING) }
98
94
  end
99
95
 
100
96
  def find_expectation(node, &block)
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks if example groups contain too many `let` and `subject` calls.
7
+ #
8
+ # This cop is configurable using the `Max` option and the `AllowSubject`
9
+ # which will configure the cop to only register offenses on calls to
10
+ # `let` and not calls to `subject`.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # describe MyClass do
15
+ # let(:foo) { [] }
16
+ # let(:bar) { [] }
17
+ # let!(:baz) { [] }
18
+ # let(:qux) { [] }
19
+ # let(:quux) { [] }
20
+ # let(:quuz) { {} }
21
+ # end
22
+ #
23
+ # describe MyClass do
24
+ # let(:foo) { [] }
25
+ # let(:bar) { [] }
26
+ # let!(:baz) { [] }
27
+ #
28
+ # context 'when stuff' do
29
+ # let(:qux) { [] }
30
+ # let(:quux) { [] }
31
+ # let(:quuz) { {} }
32
+ # end
33
+ # end
34
+ #
35
+ # # good
36
+ # describe MyClass do
37
+ # let(:bar) { [] }
38
+ # let!(:baz) { [] }
39
+ # let(:qux) { [] }
40
+ # let(:quux) { [] }
41
+ # let(:quuz) { {} }
42
+ # end
43
+ #
44
+ # describe MyClass do
45
+ # context 'when stuff' do
46
+ # let(:foo) { [] }
47
+ # let(:bar) { [] }
48
+ # let!(:booger) { [] }
49
+ # end
50
+ #
51
+ # context 'when other stuff' do
52
+ # let(:qux) { [] }
53
+ # let(:quux) { [] }
54
+ # let(:quuz) { {} }
55
+ # end
56
+ # end
57
+ #
58
+ # @example when disabling AllowSubject configuration
59
+ #
60
+ # # rubocop.yml
61
+ # # RSpec/MultipleMemoizedHelpers:
62
+ # # AllowSubject: false
63
+ #
64
+ # # bad - `subject` counts towards memoized helpers
65
+ # describe MyClass do
66
+ # subject { {} }
67
+ # let(:foo) { [] }
68
+ # let(:bar) { [] }
69
+ # let!(:baz) { [] }
70
+ # let(:qux) { [] }
71
+ # let(:quux) { [] }
72
+ # end
73
+ #
74
+ # @example with Max configuration
75
+ #
76
+ # # rubocop.yml
77
+ # # RSpec/MultipleMemoizedHelpers:
78
+ # # Max: 1
79
+ #
80
+ # # bad
81
+ # describe MyClass do
82
+ # let(:foo) { [] }
83
+ # let(:bar) { [] }
84
+ # end
85
+ #
86
+ class MultipleMemoizedHelpers < Base
87
+ include ConfigurableMax
88
+ include RuboCop::RSpec::Variable
89
+
90
+ MSG = 'Example group has too many memoized helpers [%<count>d/%<max>d]'
91
+
92
+ def on_block(node)
93
+ return unless spec_group?(node)
94
+
95
+ count = all_helpers(node).uniq.count
96
+
97
+ return if count <= max
98
+
99
+ self.max = count
100
+ add_offense(node, message: format(MSG, count: count, max: max))
101
+ end
102
+
103
+ def on_new_investigation
104
+ @example_group_memoized_helpers = {}
105
+ end
106
+
107
+ private
108
+
109
+ attr_reader :example_group_memoized_helpers
110
+
111
+ def all_helpers(node)
112
+ [
113
+ *helpers(node),
114
+ *node.each_ancestor(:block).flat_map(&method(:helpers))
115
+ ]
116
+ end
117
+
118
+ def helpers(node)
119
+ @example_group_memoized_helpers[node] ||=
120
+ variable_nodes(node).map do |variable_node|
121
+ if variable_node.block_type?
122
+ variable_definition?(variable_node.send_node)
123
+ else # block-pass (`let(:foo, &bar)`)
124
+ variable_definition?(variable_node)
125
+ end
126
+ end
127
+ end
128
+
129
+ def variable_nodes(node)
130
+ example_group = RuboCop::RSpec::ExampleGroup.new(node)
131
+ if allow_subject?
132
+ example_group.lets
133
+ else
134
+ example_group.lets + example_group.subjects
135
+ end
136
+ end
137
+
138
+ def max
139
+ cop_config['Max']
140
+ end
141
+
142
+ def allow_subject?
143
+ cop_config['AllowSubject']
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -33,7 +33,8 @@ module RuboCop
33
33
  # - If subjects are defined with `subject!` then we don't autocorrect.
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
- class MultipleSubjects < Cop
36
+ class MultipleSubjects < Base
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
@@ -41,7 +41,7 @@ module RuboCop
41
41
  #
42
42
  # it { is_expected.to be_valid }
43
43
  # end
44
- class NamedSubject < Cop
44
+ class NamedSubject < Base
45
45
  MSG = 'Name your test subject if you need '\
46
46
  'to reference it explicitly.'
47
47
 
@@ -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
 
@@ -85,9 +85,9 @@ module RuboCop
85
85
  # end
86
86
  # end
87
87
  #
88
- class NestedGroups < Cop
88
+ class NestedGroups < Base
89
89
  include ConfigurableMax
90
- include RuboCop::RSpec::TopLevelDescribe
90
+ include RuboCop::RSpec::TopLevelGroup
91
91
 
92
92
  MSG = 'Maximum example group nesting exceeded [%<total>d/%<max>d].'
93
93
 
@@ -97,13 +97,11 @@ module RuboCop
97
97
  "Configuration key `#{DEPRECATED_MAX_KEY}` for #{cop_name} is " \
98
98
  'deprecated in favor of `Max`. Please use that instead.'
99
99
 
100
- def_node_search :find_contexts, ExampleGroups::ALL.block_pattern
101
-
102
- def on_top_level_describe(node, _args)
103
- find_nested_contexts(node.parent) do |context, nesting|
100
+ def on_top_level_group(node)
101
+ find_nested_example_groups(node) do |example_group, nesting|
104
102
  self.max = nesting
105
103
  add_offense(
106
- context.send_node,
104
+ example_group.send_node,
107
105
  message: message(nesting)
108
106
  )
109
107
  end
@@ -111,13 +109,14 @@ module RuboCop
111
109
 
112
110
  private
113
111
 
114
- def find_nested_contexts(node, nesting: 1, &block)
115
- find_contexts(node) do |nested_context|
116
- yield(nested_context, nesting) if nesting > max_nesting
112
+ def find_nested_example_groups(node, nesting: 1, &block)
113
+ example_group = example_group?(node)
114
+ yield node, nesting if example_group && nesting > max_nesting
115
+
116
+ next_nesting = example_group ? nesting + 1 : nesting
117
117
 
118
- nested_context.each_child_node do |child|
119
- find_nested_contexts(child, nesting: nesting + 1, &block)
120
- end
118
+ node.each_child_node(:block, :begin) do |child|
119
+ find_nested_example_groups(child, nesting: next_nesting, &block)
121
120
  end
122
121
  end
123
122
 
@@ -15,7 +15,8 @@ module RuboCop
15
15
  # it '...' do
16
16
  # expect(false).not_to be_true
17
17
  # end
18
- class NotToNot < Cop
18
+ class NotToNot < Base
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)
@@ -21,7 +21,7 @@ module RuboCop
21
21
  # let(:foo) { bar }
22
22
  # let(:baz) { baz }
23
23
  # let!(:other) { other }
24
- class OverwritingSetup < Cop
24
+ class OverwritingSetup < Base
25
25
  MSG = '`%<name>s` is already defined.'
26
26
 
27
27
  def_node_matcher :setup?, (Helpers::ALL + Subject::ALL).block_pattern
@@ -31,7 +31,7 @@ module RuboCop
31
31
  # # good
32
32
  # describe MyClass do
33
33
  # end
34
- class Pending < Cop
34
+ class Pending < Base
35
35
  MSG = 'Pending spec found.'
36
36
 
37
37
  PENDING = Examples::PENDING + Examples::SKIPPED + ExampleGroups::SKIPPED
@@ -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)
@@ -238,18 +208,20 @@ module RuboCop
238
208
  'is_a?'
239
209
  when 'be_an_instance_of', 'be_instance_of', 'an_instance_of'
240
210
  'instance_of?'
241
- when 'include', 'respond_to'
242
- matcher + '?'
211
+ when 'include'
212
+ 'include?'
213
+ when 'respond_to'
214
+ 'respond_to?'
243
215
  when /^have_(.+)/
244
216
  "has_#{Regexp.last_match(1)}?"
245
217
  else
246
- matcher[/^be_(.+)/, 1] + '?'
218
+ "#{matcher[/^be_(.+)/, 1]}?"
247
219
  end
248
220
  end
249
221
  # rubocop:enable Metrics/MethodLength
250
222
 
251
223
  def replacement_matcher(node)
252
- case [cop_config['Strict'], node.method_name == :to]
224
+ case [cop_config['Strict'], node.method?(:to)]
253
225
  when [true, true]
254
226
  'be(true)'
255
227
  when [true, false]
@@ -261,7 +233,6 @@ module RuboCop
261
233
  end
262
234
  end
263
235
  end
264
- # rubocop:enable Metrics/ModuleLength
265
236
 
266
237
  # Prefer using predicate matcher over using predicate method directly.
267
238
  #
@@ -277,12 +248,12 @@ module RuboCop
277
248
  # expect(foo).to be_something
278
249
  #
279
250
  # # also good - It checks "true" strictly.
280
- # expect(foo).to be(true)
251
+ # expect(foo.something?).to be(true)
281
252
  #
282
253
  # @example Strict: false, EnforcedStyle: inflected
283
254
  # # bad
284
255
  # expect(foo.something?).to be_truthy
285
- # expect(foo).to be(true)
256
+ # expect(foo.something?).to be(true)
286
257
  #
287
258
  # # good
288
259
  # expect(foo).to be_something
@@ -300,7 +271,8 @@ module RuboCop
300
271
  #
301
272
  # # good - the above code is rewritten to it by this cop
302
273
  # expect(foo.something?).to be_truthy
303
- class PredicateMatcher < Cop
274
+ class PredicateMatcher < Base
275
+ extend AutoCorrector
304
276
  include ConfigurableEnforcedStyle
305
277
  include InflectedHelper
306
278
  include ExplicitHelper
@@ -318,15 +290,6 @@ module RuboCop
318
290
  check_explicit(node) if style == :explicit
319
291
  end
320
292
 
321
- def autocorrect(node)
322
- case style
323
- when :inflected
324
- autocorrect_inflected(node)
325
- when :explicit
326
- autocorrect_explicit(node)
327
- end
328
- end
329
-
330
293
  private
331
294
 
332
295
  # returns args location with whitespace