rubocop-rspec 1.12.0 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/config/default.yml +15 -1
- data/lib/rubocop-rspec.rb +2 -0
- data/lib/rubocop/cop/rspec/any_instance.rb +7 -10
- data/lib/rubocop/cop/rspec/around_block.rb +19 -30
- data/lib/rubocop/cop/rspec/be_eql.rb +3 -7
- data/lib/rubocop/cop/rspec/before_after_all.rb +10 -16
- data/lib/rubocop/cop/rspec/cop.rb +5 -1
- data/lib/rubocop/cop/rspec/describe_class.rb +8 -8
- data/lib/rubocop/cop/rspec/describe_method.rb +6 -5
- data/lib/rubocop/cop/rspec/described_class.rb +2 -2
- data/lib/rubocop/cop/rspec/example_length.rb +5 -8
- data/lib/rubocop/cop/rspec/example_wording.rb +57 -23
- data/lib/rubocop/cop/rspec/expect_actual.rb +3 -9
- data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
- data/lib/rubocop/cop/rspec/file_path.rb +30 -29
- data/lib/rubocop/cop/rspec/hook_argument.rb +1 -1
- data/lib/rubocop/cop/rspec/instance_spy.rb +12 -12
- data/lib/rubocop/cop/rspec/instance_variable.rb +2 -2
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +47 -0
- data/lib/rubocop/cop/rspec/leading_subject.rb +1 -1
- data/lib/rubocop/cop/rspec/message_chain.rb +7 -4
- data/lib/rubocop/cop/rspec/message_spies.rb +6 -5
- data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +38 -6
- data/lib/rubocop/cop/rspec/named_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/nested_groups.rb +10 -6
- data/lib/rubocop/cop/rspec/not_to_not.rb +12 -23
- data/lib/rubocop/cop/rspec/shared_context.rb +107 -0
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +16 -23
- data/lib/rubocop/cop/rspec/subject_stub.rb +4 -4
- data/lib/rubocop/cop/rspec/verified_doubles.rb +4 -3
- data/lib/rubocop/rspec/example_group.rb +1 -1
- data/lib/rubocop/rspec/language.rb +25 -7
- data/lib/rubocop/rspec/version.rb +1 -1
- data/spec/expect_violation/expectation_spec.rb +16 -16
- data/spec/project/changelog_spec.rb +1 -1
- data/spec/project/default_config_spec.rb +1 -1
- data/spec/project/project_requires_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/any_instance_spec.rb +4 -4
- data/spec/rubocop/cop/rspec/around_block_spec.rb +115 -26
- data/spec/rubocop/cop/rspec/be_eql_spec.rb +9 -9
- data/spec/rubocop/cop/rspec/before_after_all_spec.rb +38 -80
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/describe_method_spec.rb +2 -2
- data/spec/rubocop/cop/rspec/described_class_spec.rb +13 -13
- data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/example_length_spec.rb +3 -32
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +21 -2
- data/spec/rubocop/cop/rspec/expect_actual_spec.rb +33 -18
- data/spec/rubocop/cop/rspec/expect_output_spec.rb +3 -3
- data/spec/rubocop/cop/rspec/file_path_spec.rb +119 -170
- data/spec/rubocop/cop/rspec/focus_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/hook_argument_spec.rb +1 -3
- data/spec/rubocop/cop/rspec/implicit_expect_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/instance_spy_spec.rb +11 -11
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +4 -4
- data/spec/rubocop/cop/rspec/it_behaves_like_spec.rb +51 -0
- data/spec/rubocop/cop/rspec/leading_subject_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/let_setup_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/message_chain_spec.rb +3 -3
- data/spec/rubocop/cop/rspec/message_expectation_spec.rb +5 -23
- data/spec/rubocop/cop/rspec/message_spies_spec.rb +9 -23
- data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +66 -3
- data/spec/rubocop/cop/rspec/nested_groups_spec.rb +4 -4
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +3 -3
- data/spec/rubocop/cop/rspec/repeated_description_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/repeated_example_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/scattered_setup_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/shared_context_spec.rb +142 -0
- data/spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb +5 -5
- data/spec/rubocop/cop/rspec/subject_stub_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +2 -2
- data/spec/rubocop/rspec/config_formatter_spec.rb +12 -12
- data/spec/rubocop/rspec/description_extractor_spec.rb +23 -23
- data/spec/rubocop/rspec/example_group_spec.rb +11 -11
- data/spec/rubocop/rspec/example_spec.rb +1 -1
- data/spec/rubocop/rspec/language/selector_set_spec.rb +1 -1
- data/spec/rubocop/rspec/util/one_spec.rb +1 -1
- data/spec/rubocop/rspec/wording_spec.rb +1 -1
- data/spec/shared/detects_style_behavior.rb +3 -4
- data/spec/spec_helper.rb +10 -0
- metadata +8 -2
@@ -17,7 +17,7 @@ module RuboCop
|
|
17
17
|
# expect(name).to eq("John")
|
18
18
|
#
|
19
19
|
class ExpectActual < Cop
|
20
|
-
MSG = 'Provide the actual you are testing to `expect(...)
|
20
|
+
MSG = 'Provide the actual you are testing to `expect(...)`.'.freeze
|
21
21
|
|
22
22
|
SIMPLE_LITERALS = %i(
|
23
23
|
true
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
41
41
|
regexp
|
42
42
|
).freeze
|
43
43
|
|
44
|
-
def_node_matcher :
|
44
|
+
def_node_matcher :expect_literal, '(send _ :expect $#literal?)'
|
45
45
|
|
46
46
|
def on_send(node)
|
47
47
|
expect_literal(node) do |argument|
|
@@ -53,14 +53,8 @@ module RuboCop
|
|
53
53
|
|
54
54
|
# This is not implement using a NodePattern because it seems
|
55
55
|
# to not be able to match against an explicit (nil) sexp
|
56
|
-
def expect_literal(node)
|
57
|
-
return unless (argument = expect(node))
|
58
|
-
|
59
|
-
yield(argument) if literal?(argument)
|
60
|
-
end
|
61
|
-
|
62
56
|
def literal?(node)
|
63
|
-
simple_literal?(node) || complex_literal?(node)
|
57
|
+
node && (simple_literal?(node) || complex_literal?(node))
|
64
58
|
end
|
65
59
|
|
66
60
|
def simple_literal?(node)
|
@@ -15,8 +15,8 @@ module RuboCop
|
|
15
15
|
# # good
|
16
16
|
# expect { my_app.print_report }.to output('Hello World').to_stdout
|
17
17
|
class ExpectOutput < Cop
|
18
|
-
MSG = 'Use `expect { ... }.to output(...).to_%<name>s` '
|
19
|
-
'instead of mutating $%<name>s'.freeze
|
18
|
+
MSG = 'Use `expect { ... }.to output(...).to_%<name>s` '\
|
19
|
+
'instead of mutating $%<name>s.'.freeze
|
20
20
|
|
21
21
|
def_node_matcher :hook?, Hooks::ALL.block_pattern
|
22
22
|
|
@@ -44,66 +44,67 @@ module RuboCop
|
|
44
44
|
class FilePath < Cop
|
45
45
|
include RuboCop::RSpec::TopLevelDescribe
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
MSG = 'Spec path should end with `%s`.'.freeze
|
48
|
+
|
49
|
+
def_node_search :const_described?, '(send _ :describe (const ...) ...)'
|
50
|
+
def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))'
|
49
51
|
|
50
52
|
def on_top_level_describe(node, args)
|
53
|
+
return unless const_described?(node) && single_top_level_describe?
|
51
54
|
return if routing_spec?(args)
|
52
55
|
|
53
|
-
|
54
|
-
object = args.first.const_name
|
55
|
-
return unless object
|
56
|
+
glob = glob_for(args)
|
56
57
|
|
57
|
-
|
58
|
-
return if source_filename =~ regexp_from_glob(path_matcher)
|
58
|
+
return if filename_ends_with?(glob)
|
59
59
|
|
60
|
-
add_offense(node, :expression, format(
|
60
|
+
add_offense(node, :expression, format(MSG, glob))
|
61
61
|
end
|
62
62
|
|
63
63
|
private
|
64
64
|
|
65
65
|
def routing_spec?(args)
|
66
|
-
args.any?
|
67
|
-
arg.children.include?(ROUTING_PAIR)
|
68
|
-
end
|
66
|
+
args.any?(&method(:routing_metadata?))
|
69
67
|
end
|
70
68
|
|
71
|
-
def
|
72
|
-
|
73
|
-
if method && method.type.equal?(:str) && !ignore_methods?
|
74
|
-
path += '*' + method.str_content.gsub(/\W+/, '')
|
75
|
-
end
|
76
|
-
|
77
|
-
"#{path}*_spec.rb"
|
69
|
+
def glob_for((described_class, method_name))
|
70
|
+
"#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
|
78
71
|
end
|
79
72
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
73
|
+
def name_glob(name)
|
74
|
+
return unless name && name.str_type?
|
75
|
+
|
76
|
+
"*#{name.str_content.gsub(/\W/, '')}" unless ignore_methods?
|
84
77
|
end
|
85
78
|
|
86
|
-
def
|
87
|
-
|
79
|
+
def expected_path(constant)
|
80
|
+
File.join(
|
81
|
+
constant.const_name.split('::').map do |name|
|
82
|
+
custom_transform.fetch(name) { camel_to_snake_case(name) }
|
83
|
+
end
|
84
|
+
)
|
88
85
|
end
|
89
86
|
|
90
|
-
def
|
87
|
+
def camel_to_snake_case(string)
|
91
88
|
string
|
92
89
|
.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
|
93
90
|
.gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
|
94
91
|
.downcase
|
95
92
|
end
|
96
93
|
|
97
|
-
def
|
98
|
-
|
94
|
+
def custom_transform
|
95
|
+
cop_config.fetch('CustomTransform', {})
|
99
96
|
end
|
100
97
|
|
101
98
|
def ignore_methods?
|
102
99
|
cop_config['IgnoreMethods']
|
103
100
|
end
|
104
101
|
|
105
|
-
def
|
106
|
-
|
102
|
+
def filename_ends_with?(glob)
|
103
|
+
File.fnmatch?("*#{glob}", processed_source.buffer.name)
|
104
|
+
end
|
105
|
+
|
106
|
+
def relevant_rubocop_rspec_file?(_)
|
107
|
+
true
|
107
108
|
end
|
108
109
|
end
|
109
110
|
end
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
HOOKS = Hooks::ALL.node_pattern_union.freeze
|
67
67
|
|
68
68
|
def_node_matcher :scoped_hook, <<-PATTERN
|
69
|
-
|
69
|
+
(block $(send nil #{HOOKS} (sym ${:each :example})) ...)
|
70
70
|
PATTERN
|
71
71
|
|
72
72
|
def_node_matcher :unscoped_hook, "(block $(send nil #{HOOKS}) ...)"
|
@@ -19,27 +19,27 @@ module RuboCop
|
|
19
19
|
# end
|
20
20
|
#
|
21
21
|
class InstanceSpy < Cop
|
22
|
-
MSG = 'Use `instance_spy` when you check your double '
|
23
|
-
'with `have_received
|
22
|
+
MSG = 'Use `instance_spy` when you check your double '\
|
23
|
+
'with `have_received`.'.freeze
|
24
24
|
|
25
25
|
EXAMPLES = Examples::ALL.node_pattern_union.freeze
|
26
26
|
|
27
27
|
def_node_matcher :example?, "(block $(send nil #{EXAMPLES}) ...)"
|
28
28
|
|
29
29
|
def_node_search :null_double, <<-PATTERN
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
(lvasgn $_
|
31
|
+
(send
|
32
|
+
$(send nil :instance_double
|
33
|
+
...) :as_null_object))
|
34
34
|
PATTERN
|
35
35
|
|
36
36
|
def_node_search :have_received_usage, <<-PATTERN
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
(send
|
38
|
+
(send nil :expect
|
39
|
+
(lvar $_)) :to
|
40
|
+
(send nil :have_received
|
41
|
+
...)
|
41
42
|
...)
|
42
|
-
...)
|
43
43
|
PATTERN
|
44
44
|
|
45
45
|
def on_block(node)
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
|
48
48
|
null_double(node) do |var, receiver|
|
49
49
|
have_received_usage(node) do |expected|
|
50
|
-
add_offense(receiver, :expression
|
50
|
+
add_offense(receiver, :expression) if expected == var
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
# end
|
48
48
|
#
|
49
49
|
class InstanceVariable < Cop
|
50
|
-
|
50
|
+
MSG = 'Use `let` instead of an instance variable.'.freeze
|
51
51
|
|
52
52
|
EXAMPLE_GROUP_METHODS = ExampleGroups::ALL + SharedGroups::ALL
|
53
53
|
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
ivar_usage(node) do |ivar, name|
|
64
64
|
return if assignment_only? && !ivar_assigned?(node, name)
|
65
65
|
|
66
|
-
add_offense(ivar, :expression
|
66
|
+
add_offense(ivar, :expression)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that only one `it_behaves_like` style is used.
|
7
|
+
#
|
8
|
+
# @example when configuration is `EnforcedStyle: it_behaves_like`
|
9
|
+
# # bad
|
10
|
+
# it_should_behave_like 'a foo'
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# it_behaves_like 'a foo'
|
14
|
+
#
|
15
|
+
# @example when configuration is `EnforcedStyle: it_should_behave_like`
|
16
|
+
# # bad
|
17
|
+
# it_behaves_like 'a foo'
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# it_should_behave_like 'a foo'
|
21
|
+
class ItBehavesLike < Cop
|
22
|
+
include ConfigurableEnforcedStyle
|
23
|
+
|
24
|
+
MSG = 'Prefer `%s` over `%s` when including examples in '\
|
25
|
+
'a nested context.'.freeze
|
26
|
+
|
27
|
+
def_node_matcher :example_inclusion_offense, '(send _ % ...)'
|
28
|
+
|
29
|
+
def on_send(node)
|
30
|
+
example_inclusion_offense(node, alternative_style) do
|
31
|
+
add_offense(node, :expression)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def autocorrect(node)
|
36
|
+
->(corrector) { corrector.replace(node.loc.selector, style.to_s) }
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def message(_node)
|
42
|
+
format(MSG, style, alternative_style)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
# end
|
28
28
|
# end
|
29
29
|
class LeadingSubject < Cop
|
30
|
-
MSG = 'Declare `subject` above any other `let` declarations'.freeze
|
30
|
+
MSG = 'Declare `subject` above any other `let` declarations.'.freeze
|
31
31
|
|
32
32
|
def_node_matcher :subject?, '(block $(send nil :subject ...) args ...)'
|
33
33
|
|
@@ -12,13 +12,16 @@ module RuboCop
|
|
12
12
|
# allow(foo).to receive(bar: thing)
|
13
13
|
#
|
14
14
|
class MessageChain < Cop
|
15
|
-
|
15
|
+
MSG = 'Avoid stubbing using `%<method>s`.'.freeze
|
16
|
+
|
17
|
+
def_node_matcher :message_chain, Matchers::MESSAGE_CHAIN.send_pattern
|
16
18
|
|
17
19
|
def on_send(node)
|
18
|
-
|
19
|
-
|
20
|
+
message_chain(node) { add_offense(node, :selector) }
|
21
|
+
end
|
20
22
|
|
21
|
-
|
23
|
+
def message(node)
|
24
|
+
format(MSG, method: node.method_name)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
@@ -27,11 +27,12 @@ module RuboCop
|
|
27
27
|
class MessageSpies < Cop
|
28
28
|
include ConfigurableEnforcedStyle
|
29
29
|
|
30
|
-
MSG_RECEIVE = 'Prefer `receive` for setting message '
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
MSG_RECEIVE = 'Prefer `receive` for setting message '\
|
31
|
+
'expectations.'.freeze
|
32
|
+
|
33
|
+
MSG_HAVE_RECEIVED = 'Prefer `have_received` for setting message '\
|
34
|
+
'expectations. Setup `%s` as a spy using `allow`'\
|
35
|
+
' or `instance_spy`.'.freeze
|
35
36
|
|
36
37
|
SUPPORTED_STYLES = %w(have_received receive).freeze
|
37
38
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
class MultipleDescribes < Cop
|
26
26
|
include RuboCop::RSpec::TopLevelDescribe
|
27
27
|
|
28
|
-
MSG = 'Do not use multiple top level describes - '
|
28
|
+
MSG = 'Do not use multiple top level describes - '\
|
29
29
|
'try to nest them.'.freeze
|
30
30
|
|
31
31
|
def on_top_level_describe(node, _args)
|
@@ -48,22 +48,54 @@ module RuboCop
|
|
48
48
|
class MultipleExpectations < Cop
|
49
49
|
include ConfigurableMax
|
50
50
|
|
51
|
-
MSG = 'Example has too many expectations [%{total}/%{max}]'.freeze
|
51
|
+
MSG = 'Example has too many expectations [%{total}/%{max}].'.freeze
|
52
52
|
|
53
|
-
def_node_search :
|
53
|
+
def_node_search :with_aggregated_failures?, '(sym :aggregate_failures)'
|
54
|
+
def_node_search :disabled_aggregated_failures?, <<-PATTERN
|
55
|
+
(pair (sym :aggregate_failures) (false))
|
56
|
+
PATTERN
|
57
|
+
|
58
|
+
def_node_matcher :expect?, '(send _ :expect ...)'
|
59
|
+
def_node_matcher :aggregate_failures?, <<-PATTERN
|
60
|
+
(block (send _ :aggregate_failures ...) ...)
|
61
|
+
PATTERN
|
54
62
|
|
55
63
|
def on_block(node)
|
56
|
-
return unless example?(node)
|
64
|
+
return unless example?(node)
|
65
|
+
|
66
|
+
return if example_with_aggregated_failures?(node)
|
67
|
+
|
68
|
+
expectations_count = to_enum(:find_expectation, node).count
|
57
69
|
|
58
|
-
return if
|
70
|
+
return if expectations_count <= max_expectations
|
59
71
|
|
60
|
-
self.max =
|
72
|
+
self.max = expectations_count
|
61
73
|
|
62
|
-
flag_example(node, expectation_count:
|
74
|
+
flag_example(node, expectation_count: expectations_count)
|
63
75
|
end
|
64
76
|
|
65
77
|
private
|
66
78
|
|
79
|
+
def example_with_aggregated_failures?(node)
|
80
|
+
example = node.children.first
|
81
|
+
|
82
|
+
with_aggregated_failures?(example) &&
|
83
|
+
!disabled_aggregated_failures?(example)
|
84
|
+
end
|
85
|
+
|
86
|
+
def find_expectation(node, &block)
|
87
|
+
return unless node.is_a?(Parser::AST::Node)
|
88
|
+
|
89
|
+
yield if expect?(node) || aggregate_failures?(node)
|
90
|
+
|
91
|
+
# do not search inside of aggregate_failures block
|
92
|
+
return if aggregate_failures?(node)
|
93
|
+
|
94
|
+
node.children.each do |child|
|
95
|
+
find_expectation(child, &block)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
67
99
|
def flag_example(node, expectation_count:)
|
68
100
|
method, = *node
|
69
101
|
|
@@ -38,8 +38,8 @@ module RuboCop
|
|
38
38
|
# it { should be_valid }
|
39
39
|
# end
|
40
40
|
class NamedSubject < Cop
|
41
|
-
MSG = 'Name your test subject if '\
|
42
|
-
'
|
41
|
+
MSG = 'Name your test subject if you need '\
|
42
|
+
'to reference it explicitly.'.freeze
|
43
43
|
|
44
44
|
def_node_matcher :rspec_block?, <<-PATTERN
|
45
45
|
(block
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module RSpec
|
6
6
|
# Checks for nested example groups.
|
7
7
|
#
|
8
|
-
# This cop is configurable using the `
|
8
|
+
# This cop is configurable using the `Max` option
|
9
9
|
#
|
10
10
|
# @example
|
11
11
|
# # bad
|
@@ -56,7 +56,7 @@ module RuboCop
|
|
56
56
|
#
|
57
57
|
# # .rubocop.yml
|
58
58
|
# RSpec/NestedGroups:
|
59
|
-
#
|
59
|
+
# Max: 2
|
60
60
|
#
|
61
61
|
# context 'when using some feature' do
|
62
62
|
# let(:some) { :various }
|
@@ -87,7 +87,7 @@ module RuboCop
|
|
87
87
|
class NestedGroups < Cop
|
88
88
|
include RuboCop::RSpec::TopLevelDescribe
|
89
89
|
|
90
|
-
MSG = 'Maximum example group nesting exceeded'.freeze
|
90
|
+
MSG = 'Maximum example group nesting exceeded [%d/%d].'.freeze
|
91
91
|
|
92
92
|
DEPRECATED_MAX_KEY = 'MaxNesting'.freeze
|
93
93
|
|
@@ -98,8 +98,8 @@ module RuboCop
|
|
98
98
|
def_node_search :find_contexts, ExampleGroups::ALL.block_pattern
|
99
99
|
|
100
100
|
def on_top_level_describe(node, _)
|
101
|
-
find_nested_contexts(node.parent) do |context|
|
102
|
-
add_offense(context.children.first, :expression)
|
101
|
+
find_nested_contexts(node.parent) do |context, nesting|
|
102
|
+
add_offense(context.children.first, :expression, message(nesting))
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
|
108
108
|
def find_nested_contexts(node, nesting: 1, &block)
|
109
109
|
find_contexts(node) do |nested_context|
|
110
|
-
yield(nested_context) if nesting > max_nesting
|
110
|
+
yield(nested_context, nesting) if nesting > max_nesting
|
111
111
|
|
112
112
|
nested_context.each_child_node do |child|
|
113
113
|
find_nested_contexts(child, nesting: nesting + 1, &block)
|
@@ -115,6 +115,10 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
def message(nesting)
|
119
|
+
format(MSG, nesting, max_nesting)
|
120
|
+
end
|
121
|
+
|
118
122
|
def max_nesting
|
119
123
|
@max_nesting ||= Integer(max_nesting_config)
|
120
124
|
end
|