rubocop-rspec 1.38.1 → 1.43.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -0
- data/CODE_OF_CONDUCT.md +17 -0
- data/README.md +1 -61
- data/config/default.yml +159 -19
- data/lib/rubocop-rspec.rb +5 -2
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +12 -19
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +12 -19
- data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
- data/lib/rubocop/cop/rspec/around_block.rb +1 -1
- data/lib/rubocop/cop/rspec/base.rb +74 -0
- data/lib/rubocop/cop/rspec/be.rb +2 -2
- data/lib/rubocop/cop/rspec/be_eql.rb +6 -6
- data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +19 -17
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +14 -12
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +69 -0
- data/lib/rubocop/cop/rspec/context_method.rb +7 -9
- data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
- data/lib/rubocop/cop/rspec/cop.rb +3 -87
- data/lib/rubocop/cop/rspec/describe_class.rb +29 -23
- data/lib/rubocop/cop/rspec/describe_method.rb +14 -7
- data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
- data/lib/rubocop/cop/rspec/described_class.rb +12 -9
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
- data/lib/rubocop/cop/rspec/dialect.rb +5 -12
- data/lib/rubocop/cop/rspec/empty_example_group.rb +91 -7
- data/lib/rubocop/cop/rspec/empty_hook.rb +46 -0
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +5 -7
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +5 -9
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +8 -8
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +5 -9
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +6 -6
- data/lib/rubocop/cop/rspec/example_length.rb +1 -1
- data/lib/rubocop/cop/rspec/example_without_description.rb +1 -1
- data/lib/rubocop/cop/rspec/example_wording.rb +10 -11
- data/lib/rubocop/cop/rspec/expect_actual.rb +8 -11
- data/lib/rubocop/cop/rspec/expect_change.rb +10 -35
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +3 -3
- data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +24 -21
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +20 -22
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +7 -8
- data/lib/rubocop/cop/rspec/file_path.rb +57 -21
- data/lib/rubocop/cop/rspec/focus.rb +7 -11
- data/lib/rubocop/cop/rspec/hook_argument.rb +16 -23
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +10 -29
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_expect.rb +7 -15
- data/lib/rubocop/cop/rspec/implicit_subject.rb +16 -11
- data/lib/rubocop/cop/rspec/instance_spy.rb +18 -12
- data/lib/rubocop/cop/rspec/instance_variable.rb +4 -8
- data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +3 -6
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +5 -6
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/leading_subject.rb +22 -26
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +2 -5
- data/lib/rubocop/cop/rspec/let_before_examples.rb +10 -26
- data/lib/rubocop/cop/rspec/let_setup.rb +21 -6
- data/lib/rubocop/cop/rspec/message_chain.rb +7 -6
- data/lib/rubocop/cop/rspec/message_expectation.rb +2 -2
- data/lib/rubocop/cop/rspec/message_spies.rb +2 -3
- data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_describes.rb +11 -8
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +7 -11
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +148 -0
- data/lib/rubocop/cop/rspec/multiple_subjects.rb +18 -19
- data/lib/rubocop/cop/rspec/named_subject.rb +8 -8
- data/lib/rubocop/cop/rspec/nested_groups.rb +12 -13
- data/lib/rubocop/cop/rspec/not_to_not.rb +5 -6
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/pending.rb +1 -1
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +32 -69
- data/lib/rubocop/cop/rspec/rails/http_status.rb +7 -9
- data/lib/rubocop/cop/rspec/receive_counts.rb +15 -17
- data/lib/rubocop/cop/rspec/receive_never.rb +12 -12
- data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example.rb +2 -2
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +12 -2
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
- data/lib/rubocop/cop/rspec/return_from_stub.rb +12 -22
- data/lib/rubocop/cop/rspec/scattered_let.rb +12 -2
- data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_context.rb +8 -21
- data/lib/rubocop/cop/rspec/shared_examples.rb +7 -9
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +15 -18
- data/lib/rubocop/cop/rspec/subject_stub.rb +25 -53
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +56 -0
- data/lib/rubocop/cop/rspec/variable_name.rb +66 -0
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
- data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/yield.rb +14 -11
- data/lib/rubocop/cop/rspec_cops.rb +6 -1
- data/lib/rubocop/rspec/corrector/move_node.rb +54 -0
- data/lib/rubocop/rspec/description_extractor.rb +2 -6
- data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -10
- data/lib/rubocop/rspec/example_group.rb +21 -49
- data/lib/rubocop/rspec/factory_bot.rb +7 -1
- data/lib/rubocop/rspec/language.rb +13 -3
- data/lib/rubocop/rspec/language/node_pattern.rb +11 -2
- data/lib/rubocop/rspec/top_level_describe.rb +2 -2
- data/lib/rubocop/rspec/top_level_group.rb +55 -0
- data/lib/rubocop/rspec/variable.rb +16 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +36 -13
- data/lib/rubocop/rspec/util.rb +0 -19
@@ -22,7 +22,7 @@ module RuboCop
|
|
22
22
|
# let(:foo) do
|
23
23
|
# instance_double("ClassName", method_name: 'returned value')
|
24
24
|
# end
|
25
|
-
class VerifiedDoubles <
|
25
|
+
class VerifiedDoubles < Base
|
26
26
|
MSG = 'Prefer using verifying doubles over normal doubles.'
|
27
27
|
|
28
28
|
def_node_matcher :unverified_double, <<-PATTERN
|
@@ -11,7 +11,8 @@ module RuboCop
|
|
11
11
|
#
|
12
12
|
# # good
|
13
13
|
# expect(foo).to be(:bar).and_yield(1)
|
14
|
-
class Yield <
|
14
|
+
class Yield < Base
|
15
|
+
extend AutoCorrector
|
15
16
|
include RangeHelp
|
16
17
|
|
17
18
|
MSG = 'Use `.and_yield`.'
|
@@ -27,22 +28,24 @@ module RuboCop
|
|
27
28
|
|
28
29
|
block_arg(node.arguments) do |block|
|
29
30
|
if calling_block?(node.body, block)
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
31
|
+
range = block_range(node)
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
)
|
40
|
-
corrector.replace(node_range, generate_replacement(node.body))
|
33
|
+
add_offense(range) do |corrector|
|
34
|
+
autocorrect(corrector, node, range)
|
35
|
+
end
|
36
|
+
end
|
41
37
|
end
|
42
38
|
end
|
43
39
|
|
44
40
|
private
|
45
41
|
|
42
|
+
def autocorrect(corrector, node, range)
|
43
|
+
corrector.replace(
|
44
|
+
range_with_surrounding_space(range: range, side: :left),
|
45
|
+
generate_replacement(node.body)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
46
49
|
def calling_block?(node, block)
|
47
50
|
if node.begin_type?
|
48
51
|
node.each_child_node.all? { |child| block_call?(child, block) }
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'rspec/capybara/current_path_expectation'
|
4
4
|
require_relative 'rspec/capybara/feature_methods'
|
5
|
+
require_relative 'rspec/capybara/visibility_matcher'
|
5
6
|
|
6
7
|
require_relative 'rspec/factory_bot/attribute_defined_statically'
|
7
8
|
require_relative 'rspec/factory_bot/create_list'
|
@@ -9,7 +10,7 @@ require_relative 'rspec/factory_bot/factory_class_name'
|
|
9
10
|
|
10
11
|
begin
|
11
12
|
require_relative 'rspec/rails/http_status'
|
12
|
-
rescue LoadError
|
13
|
+
rescue LoadError
|
13
14
|
# Rails/HttpStatus cannot be loaded if rack/utils is unavailable.
|
14
15
|
end
|
15
16
|
|
@@ -29,6 +30,7 @@ require_relative 'rspec/described_class'
|
|
29
30
|
require_relative 'rspec/described_class_module_wrapping'
|
30
31
|
require_relative 'rspec/dialect'
|
31
32
|
require_relative 'rspec/empty_example_group'
|
33
|
+
require_relative 'rspec/empty_hook'
|
32
34
|
require_relative 'rspec/empty_line_after_example'
|
33
35
|
require_relative 'rspec/empty_line_after_example_group'
|
34
36
|
require_relative 'rspec/empty_line_after_final_let'
|
@@ -63,6 +65,7 @@ require_relative 'rspec/message_spies'
|
|
63
65
|
require_relative 'rspec/missing_example_group_argument'
|
64
66
|
require_relative 'rspec/multiple_describes'
|
65
67
|
require_relative 'rspec/multiple_expectations'
|
68
|
+
require_relative 'rspec/multiple_memoized_helpers'
|
66
69
|
require_relative 'rspec/multiple_subjects'
|
67
70
|
require_relative 'rspec/named_subject'
|
68
71
|
require_relative 'rspec/nested_groups'
|
@@ -84,6 +87,8 @@ require_relative 'rspec/shared_examples'
|
|
84
87
|
require_relative 'rspec/single_argument_message_chain'
|
85
88
|
require_relative 'rspec/subject_stub'
|
86
89
|
require_relative 'rspec/unspecified_exception'
|
90
|
+
require_relative 'rspec/variable_definition'
|
91
|
+
require_relative 'rspec/variable_name'
|
87
92
|
require_relative 'rspec/verified_doubles'
|
88
93
|
require_relative 'rspec/void_expect'
|
89
94
|
require_relative 'rspec/yield'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
module Corrector
|
6
|
+
# Helper methods to move a node
|
7
|
+
class MoveNode
|
8
|
+
include RuboCop::Cop::RangeHelp
|
9
|
+
include RuboCop::RSpec::FinalEndLocation
|
10
|
+
|
11
|
+
attr_reader :original, :corrector, :processed_source
|
12
|
+
|
13
|
+
def initialize(node, corrector, processed_source)
|
14
|
+
@original = node
|
15
|
+
@corrector = corrector
|
16
|
+
@processed_source = processed_source # used by RangeHelp
|
17
|
+
end
|
18
|
+
|
19
|
+
def move_before(other)
|
20
|
+
position = other.loc.expression
|
21
|
+
indent = ' ' * other.loc.column
|
22
|
+
newline_indent = "\n#{indent}"
|
23
|
+
|
24
|
+
corrector.insert_before(position, source(original) + newline_indent)
|
25
|
+
corrector.remove(node_range_with_surrounding_space(original))
|
26
|
+
end
|
27
|
+
|
28
|
+
def move_after(other)
|
29
|
+
position = final_end_location(other)
|
30
|
+
indent = ' ' * other.loc.column
|
31
|
+
newline_indent = "\n#{indent}"
|
32
|
+
|
33
|
+
corrector.insert_after(position, newline_indent + source(original))
|
34
|
+
corrector.remove(node_range_with_surrounding_space(original))
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def source(node)
|
40
|
+
node_range(node).source
|
41
|
+
end
|
42
|
+
|
43
|
+
def node_range(node)
|
44
|
+
node.loc.expression.with(end_pos: final_end_location(node).end_pos)
|
45
|
+
end
|
46
|
+
|
47
|
+
def node_range_with_surrounding_space(node)
|
48
|
+
range = node_range(node)
|
49
|
+
range_by_whole_lines(range, include_final_newline: true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
|
22
22
|
# Decorator of a YARD code object for working with documented rspec cops
|
23
23
|
class CodeObject
|
24
|
-
|
24
|
+
COP_CLASS_NAME = 'RuboCop::Cop::RSpec::Base'
|
25
25
|
RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec'
|
26
26
|
|
27
27
|
def initialize(yardoc)
|
@@ -68,11 +68,7 @@ module RuboCop
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def cop_subclass?
|
71
|
-
|
72
|
-
# RuboCop::Cop::WorkaroundCop are shown as having RuboCop::Cop as
|
73
|
-
# superclass, while all the following classes are listed as having
|
74
|
-
# RuboCop::Cop::RSpec::Cop as their superclass.
|
75
|
-
COP_CLASS_NAMES.include?(yardoc.superclass.path)
|
71
|
+
yardoc.superclass.path == COP_CLASS_NAME
|
76
72
|
end
|
77
73
|
|
78
74
|
def abstract?
|
@@ -2,12 +2,23 @@
|
|
2
2
|
|
3
3
|
module RuboCop
|
4
4
|
module RSpec
|
5
|
-
# Helps determine the offending location if there is not
|
5
|
+
# Helps determine the offending location if there is not an empty line
|
6
6
|
# following the node. Allows comments to follow directly after.
|
7
|
-
module
|
7
|
+
module EmptyLineSeparation
|
8
8
|
include FinalEndLocation
|
9
9
|
include RuboCop::Cop::RangeHelp
|
10
10
|
|
11
|
+
def missing_separating_line_offense(node)
|
12
|
+
return if last_child?(node)
|
13
|
+
|
14
|
+
missing_separating_line(node) do |location|
|
15
|
+
msg = yield(node.method_name)
|
16
|
+
add_offense(location, message: msg) do |corrector|
|
17
|
+
corrector.insert_after(location.end, "\n")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
11
22
|
def missing_separating_line(node)
|
12
23
|
line = final_end_location(node).line
|
13
24
|
|
@@ -32,14 +43,6 @@ module RuboCop
|
|
32
43
|
|
33
44
|
node.equal?(node.parent.children.last)
|
34
45
|
end
|
35
|
-
|
36
|
-
def autocorrect(node)
|
37
|
-
lambda do |corrector|
|
38
|
-
missing_separating_line(node) do |location|
|
39
|
-
corrector.insert_after(location.end, "\n")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
@@ -14,72 +14,44 @@ module RuboCop
|
|
14
14
|
ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL
|
15
15
|
).block_pattern
|
16
16
|
|
17
|
+
def lets
|
18
|
+
find_all_in_scope(node, :let?)
|
19
|
+
end
|
20
|
+
|
17
21
|
def subjects
|
18
|
-
|
22
|
+
find_all_in_scope(node, :subject?)
|
19
23
|
end
|
20
24
|
|
21
25
|
def examples
|
22
|
-
|
26
|
+
find_all_in_scope(node, :example?).map(&Example.public_method(:new))
|
23
27
|
end
|
24
28
|
|
25
29
|
def hooks
|
26
|
-
|
30
|
+
find_all_in_scope(node, :hook?).map(&Hook.public_method(:new))
|
27
31
|
end
|
28
32
|
|
29
33
|
private
|
30
34
|
|
31
|
-
|
32
|
-
node.each_child_node.flat_map do |child|
|
33
|
-
find_subjects(child)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def find_subjects(node)
|
38
|
-
return [] if scope_change?(node)
|
39
|
-
|
40
|
-
if subject?(node)
|
41
|
-
[node]
|
42
|
-
else
|
43
|
-
subjects_in_scope(node)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def hooks_in_scope(node)
|
48
|
-
node.each_child_node.flat_map do |child|
|
49
|
-
find_hooks(child)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def find_hooks(node)
|
54
|
-
return [] if scope_change?(node) || example?(node)
|
55
|
-
|
56
|
-
if hook?(node)
|
57
|
-
[node]
|
58
|
-
else
|
59
|
-
hooks_in_scope(node)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def examples_in_scope(node, &blk)
|
64
|
-
node.each_child_node.flat_map do |child|
|
65
|
-
find_examples(child, &blk)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Recursively search for examples within the current scope
|
35
|
+
# Recursively search for predicate within the current scope
|
70
36
|
#
|
71
|
-
# Searches node
|
37
|
+
# Searches node and halts when a scope change is detected
|
72
38
|
#
|
73
|
-
# @param node [RuboCop::Node] node to recursively search
|
39
|
+
# @param node [RuboCop::AST::Node] node to recursively search
|
74
40
|
#
|
75
|
-
# @return [Array<RuboCop::Node>] discovered
|
76
|
-
def
|
77
|
-
|
41
|
+
# @return [Array<RuboCop::AST::Node>] discovered nodes
|
42
|
+
def find_all_in_scope(node, predicate)
|
43
|
+
node.each_child_node.flat_map do |child|
|
44
|
+
find_all(child, predicate)
|
45
|
+
end
|
46
|
+
end
|
78
47
|
|
79
|
-
|
48
|
+
def find_all(node, predicate)
|
49
|
+
if public_send(predicate, node)
|
80
50
|
[node]
|
51
|
+
elsif scope_change?(node) || example?(node)
|
52
|
+
[]
|
81
53
|
else
|
82
|
-
|
54
|
+
find_all_in_scope(node, predicate)
|
83
55
|
end
|
84
56
|
end
|
85
57
|
end
|
@@ -4,7 +4,13 @@ module RuboCop
|
|
4
4
|
module RSpec
|
5
5
|
# RuboCop FactoryBot project namespace
|
6
6
|
module FactoryBot
|
7
|
-
ATTRIBUTE_DEFINING_METHODS = %i[
|
7
|
+
ATTRIBUTE_DEFINING_METHODS = %i[
|
8
|
+
factory
|
9
|
+
ignore
|
10
|
+
trait
|
11
|
+
traits_for_enum
|
12
|
+
transient
|
13
|
+
].freeze
|
8
14
|
|
9
15
|
UNPROXIED_METHODS = %i[
|
10
16
|
__send__
|
@@ -4,8 +4,6 @@ module RuboCop
|
|
4
4
|
module RSpec
|
5
5
|
# RSpec public API methods that are commonly used in cops
|
6
6
|
module Language
|
7
|
-
RSPEC = '{(const {nil? cbase} :RSpec) nil?}'
|
8
|
-
|
9
7
|
# Set of method selectors
|
10
8
|
class SelectorSet
|
11
9
|
def initialize(selectors)
|
@@ -28,8 +26,20 @@ module RuboCop
|
|
28
26
|
"(block #{send_pattern} ...)"
|
29
27
|
end
|
30
28
|
|
29
|
+
def block_pass_pattern
|
30
|
+
"(send #rspec? #{node_pattern_union} _ block_pass)"
|
31
|
+
end
|
32
|
+
|
33
|
+
def block_or_block_pass_pattern
|
34
|
+
"{#{block_pattern} #{block_pass_pattern}}"
|
35
|
+
end
|
36
|
+
|
31
37
|
def send_pattern
|
32
|
-
"(send #
|
38
|
+
"(send #rspec? #{node_pattern_union} ...)"
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_or_block_or_block_pass_pattern
|
42
|
+
"{#{send_pattern} #{block_pattern} #{block_pass_pattern}}"
|
33
43
|
end
|
34
44
|
|
35
45
|
def node_pattern_union
|
@@ -7,17 +7,26 @@ module RuboCop
|
|
7
7
|
module NodePattern
|
8
8
|
extend RuboCop::NodePattern::Macros
|
9
9
|
|
10
|
+
def_node_matcher :rspec?, '{(const {nil? cbase} :RSpec) nil?}'
|
11
|
+
|
10
12
|
def_node_matcher :example_group?, ExampleGroups::ALL.block_pattern
|
13
|
+
def_node_matcher :shared_group?, SharedGroups::ALL.block_pattern
|
14
|
+
|
15
|
+
spec_groups = ExampleGroups::ALL + SharedGroups::ALL
|
16
|
+
def_node_matcher :spec_group?, spec_groups.block_pattern
|
11
17
|
|
12
18
|
def_node_matcher :example_group_with_body?, <<-PATTERN
|
13
|
-
(block #{ExampleGroups::ALL.send_pattern} args
|
19
|
+
(block #{ExampleGroups::ALL.send_pattern} args !nil?)
|
14
20
|
PATTERN
|
15
21
|
|
16
22
|
def_node_matcher :example?, Examples::ALL.block_pattern
|
17
23
|
|
18
24
|
def_node_matcher :hook?, Hooks::ALL.block_pattern
|
19
25
|
|
20
|
-
def_node_matcher :let?, Helpers::ALL.
|
26
|
+
def_node_matcher :let?, Helpers::ALL.block_or_block_pass_pattern
|
27
|
+
|
28
|
+
def_node_matcher :include?,
|
29
|
+
Includes::ALL.send_or_block_or_block_pass_pattern
|
21
30
|
|
22
31
|
def_node_matcher :subject?, Subject::ALL.block_pattern
|
23
32
|
end
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def top_level_describe?(node)
|
19
|
-
return false unless node.
|
19
|
+
return false unless node.method?(:describe)
|
20
20
|
|
21
21
|
top_level_nodes.include?(node)
|
22
22
|
end
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
|
45
45
|
def describe_statement_children(node)
|
46
46
|
node.each_child_node(:send).select do |element|
|
47
|
-
element.
|
47
|
+
element.method?(:describe)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
# Helper methods for top level example group cops
|
6
|
+
module TopLevelGroup
|
7
|
+
extend RuboCop::NodePattern::Macros
|
8
|
+
include RuboCop::RSpec::Language
|
9
|
+
|
10
|
+
def_node_matcher :example_or_shared_group?,
|
11
|
+
(ExampleGroups::ALL + SharedGroups::ALL).block_pattern
|
12
|
+
|
13
|
+
def on_new_investigation
|
14
|
+
super
|
15
|
+
|
16
|
+
return unless root_node
|
17
|
+
|
18
|
+
top_level_groups.each do |node|
|
19
|
+
example_group?(node, &method(:on_top_level_example_group))
|
20
|
+
on_top_level_group(node)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def top_level_groups
|
25
|
+
@top_level_groups ||=
|
26
|
+
top_level_nodes(root_node).select { |n| example_or_shared_group?(n) }
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Dummy methods to be overridden in the consumer
|
32
|
+
def on_top_level_example_group; end
|
33
|
+
|
34
|
+
def on_top_level_group; end
|
35
|
+
|
36
|
+
def top_level_group?(node)
|
37
|
+
top_level_groups.include?(node)
|
38
|
+
end
|
39
|
+
|
40
|
+
def top_level_nodes(node)
|
41
|
+
if node.begin_type?
|
42
|
+
node.children
|
43
|
+
elsif node.module_type? || node.class_type?
|
44
|
+
top_level_nodes(node.body)
|
45
|
+
else
|
46
|
+
[node]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def root_node
|
51
|
+
processed_source.ast
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|