rubocop-rspec 2.29.1 → 3.5.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 +92 -3
- data/README.md +21 -5
- data/config/default.yml +64 -269
- data/config/obsoletion.yml +20 -21
- data/lib/rubocop/cop/rspec/around_block.rb +2 -4
- data/lib/rubocop/cop/rspec/base.rb +0 -1
- data/lib/rubocop/cop/rspec/be_eq.rb +1 -1
- data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
- data/lib/rubocop/cop/rspec/be_nil.rb +4 -0
- data/lib/rubocop/cop/rspec/change_by_zero.rb +4 -5
- data/lib/rubocop/cop/rspec/contain_exactly.rb +1 -0
- data/lib/rubocop/cop/rspec/context_wording.rb +15 -9
- data/lib/rubocop/cop/rspec/dialect.rb +13 -0
- data/lib/rubocop/cop/rspec/empty_example_group.rb +2 -0
- data/lib/rubocop/cop/rspec/empty_metadata.rb +1 -0
- data/lib/rubocop/cop/rspec/example_wording.rb +3 -5
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_actual.rb +3 -3
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_in_let.rb +42 -0
- data/lib/rubocop/cop/rspec/focus.rb +14 -16
- data/lib/rubocop/cop/rspec/implicit_expect.rb +3 -3
- data/lib/rubocop/cop/rspec/implicit_subject.rb +8 -0
- data/lib/rubocop/cop/rspec/indexed_let.rb +6 -3
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/match_array.rb +1 -0
- data/lib/rubocop/cop/rspec/message_spies.rb +4 -0
- data/lib/rubocop/cop/rspec/metadata_style.rb +1 -6
- data/lib/rubocop/cop/rspec/missing_expectation_target_method.rb +54 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +5 -8
- data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +7 -0
- data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +4 -4
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +4 -5
- data/lib/rubocop/cop/rspec/named_subject.rb +5 -2
- data/lib/rubocop/cop/rspec/nested_groups.rb +2 -1
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +0 -5
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +25 -11
- data/lib/rubocop/cop/rspec/remove_const.rb +0 -1
- data/lib/rubocop/cop/rspec/repeated_subject_call.rb +1 -0
- data/lib/rubocop/cop/rspec/return_from_stub.rb +5 -4
- data/lib/rubocop/cop/rspec/scattered_setup.rb +7 -1
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +3 -4
- data/lib/rubocop/cop/rspec/sort_metadata.rb +22 -8
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +15 -10
- data/lib/rubocop/cop/rspec/subject_stub.rb +2 -2
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +21 -14
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +14 -53
- data/lib/rubocop/cop/rspec/void_expect.rb +6 -1
- data/lib/rubocop/cop/rspec_cops.rb +2 -25
- data/lib/rubocop/rspec/concept.rb +0 -1
- data/lib/rubocop/rspec/config_formatter.rb +4 -32
- data/lib/rubocop/rspec/cop/generator.rb +25 -0
- data/lib/rubocop/rspec/description_extractor.rb +2 -2
- data/lib/rubocop/rspec/hook.rb +1 -1
- data/lib/rubocop/rspec/language.rb +0 -1
- data/lib/rubocop/rspec/node.rb +1 -1
- data/lib/rubocop/rspec/plugin.rb +37 -0
- data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +1 -1
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop/rspec/wording.rb +2 -4
- data/lib/rubocop/rspec.rb +0 -7
- data/lib/rubocop-rspec.rb +2 -20
- metadata +18 -62
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +0 -39
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +0 -104
- data/lib/rubocop/cop/rspec/capybara/match_style.rb +0 -38
- data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +0 -33
- data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +0 -29
- data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +0 -24
- data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +0 -35
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +0 -36
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +0 -35
- data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +0 -50
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +0 -40
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +0 -29
- data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +0 -33
- data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +0 -55
- data/lib/rubocop/cop/rspec/file_path.rb +0 -179
- data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +0 -27
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +0 -35
- data/lib/rubocop/cop/rspec/rails/http_status.rb +0 -61
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +0 -62
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +0 -39
- data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +0 -39
- data/lib/rubocop/cop/rspec/rails/travel_around.rb +0 -34
- data/lib/rubocop/rspec/inject.rb +0 -18
- data/lib/rubocop/rspec/language/node_pattern.rb +0 -48
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
|
46
46
|
# @!method eql_type_with_identity(node)
|
47
47
|
def_node_matcher :eql_type_with_identity, <<~PATTERN
|
48
|
-
(send _ :to $(send nil? :eql {
|
48
|
+
(send _ :to $(send nil? :eql {boolean int float sym nil}))
|
49
49
|
PATTERN
|
50
50
|
|
51
51
|
def on_send(node)
|
@@ -101,24 +101,23 @@ module RuboCop
|
|
101
101
|
|
102
102
|
private
|
103
103
|
|
104
|
-
# rubocop:disable Metrics/MethodLength
|
105
104
|
def register_offense(node, change_node)
|
106
105
|
if compound_expectations?(node)
|
107
|
-
add_offense(node
|
106
|
+
add_offense(node,
|
108
107
|
message: message_compound(change_node)) do |corrector|
|
109
108
|
autocorrect_compound(corrector, node)
|
110
109
|
end
|
111
110
|
else
|
112
|
-
add_offense(node
|
111
|
+
add_offense(node,
|
113
112
|
message: message(change_node)) do |corrector|
|
114
113
|
autocorrect(corrector, node, change_node)
|
115
114
|
end
|
116
115
|
end
|
117
116
|
end
|
118
|
-
# rubocop:enable Metrics/MethodLength
|
119
117
|
|
120
118
|
def compound_expectations?(node)
|
121
|
-
|
119
|
+
node.parent.send_type? &&
|
120
|
+
%i[and or & |].include?(node.parent.method_name)
|
122
121
|
end
|
123
122
|
|
124
123
|
def message(change_node)
|
@@ -12,6 +12,9 @@ module RuboCop
|
|
12
12
|
#
|
13
13
|
# @see http://www.betterspecs.org/#contexts
|
14
14
|
#
|
15
|
+
# If both `Prefixes` and `AllowedPatterns` are empty, this cop will always
|
16
|
+
# report an offense. So you need to set at least one of them.
|
17
|
+
#
|
15
18
|
# @example `Prefixes` configuration
|
16
19
|
# # .rubocop.yml
|
17
20
|
# # RSpec/ContextWording:
|
@@ -58,7 +61,9 @@ module RuboCop
|
|
58
61
|
class ContextWording < Base
|
59
62
|
include AllowedPattern
|
60
63
|
|
61
|
-
|
64
|
+
MSG_MATCH = 'Context description should match %<patterns>s.'
|
65
|
+
MSG_ALWAYS = 'Current settings will always report an offense. Please ' \
|
66
|
+
'add allowed words to `Prefixes` or `AllowedPatterns`.'
|
62
67
|
|
63
68
|
# @!method context_wording(node)
|
64
69
|
def_node_matcher :context_wording, <<~PATTERN
|
@@ -67,8 +72,7 @@ module RuboCop
|
|
67
72
|
|
68
73
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
69
74
|
context_wording(node) do |context|
|
70
|
-
|
71
|
-
message = format(MSG, patterns: expect_patterns)
|
75
|
+
unless matches_allowed_pattern?(description(context))
|
72
76
|
add_offense(context, message: message)
|
73
77
|
end
|
74
78
|
end
|
@@ -84,12 +88,6 @@ module RuboCop
|
|
84
88
|
@prefix_regexes ||= prefixes.map { |pre| /^#{Regexp.escape(pre)}\b/ }
|
85
89
|
end
|
86
90
|
|
87
|
-
def bad_pattern?(node)
|
88
|
-
return false if allowed_patterns.empty?
|
89
|
-
|
90
|
-
!matches_allowed_pattern?(description(node))
|
91
|
-
end
|
92
|
-
|
93
91
|
def description(context)
|
94
92
|
if context.xstr_type?
|
95
93
|
context.value.value
|
@@ -98,6 +96,14 @@ module RuboCop
|
|
98
96
|
end
|
99
97
|
end
|
100
98
|
|
99
|
+
def message
|
100
|
+
if allowed_patterns.empty?
|
101
|
+
MSG_ALWAYS
|
102
|
+
else
|
103
|
+
format(MSG_MATCH, patterns: expect_patterns)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
101
107
|
def expect_patterns
|
102
108
|
inspected = allowed_patterns.map do |pattern|
|
103
109
|
pattern.inspect.gsub(/\A"|"\z/, '/')
|
@@ -29,6 +29,19 @@ module RuboCop
|
|
29
29
|
# PreferredMethods:
|
30
30
|
# context: describe
|
31
31
|
#
|
32
|
+
# If you were previously using the `RSpec/Capybara/FeatureMethods` cop and
|
33
|
+
# want to keep disabling all Capybara-specific methods that have the same
|
34
|
+
# native RSpec method (e.g. are just aliases), use the following config:
|
35
|
+
#
|
36
|
+
# RSpec/Dialect:
|
37
|
+
# PreferredMethods:
|
38
|
+
# background: :before
|
39
|
+
# scenario: :it
|
40
|
+
# xscenario: :xit
|
41
|
+
# given: :let
|
42
|
+
# given!: :let!
|
43
|
+
# feature: :describe
|
44
|
+
#
|
32
45
|
# You can expect the following behavior:
|
33
46
|
#
|
34
47
|
# @example
|
@@ -130,6 +130,7 @@ module RuboCop
|
|
130
130
|
def_node_matcher :examples?, <<~PATTERN
|
131
131
|
{
|
132
132
|
#examples_directly_or_in_block?
|
133
|
+
#examples_in_branches?
|
133
134
|
(begin <#examples_directly_or_in_block? ...>)
|
134
135
|
(begin <#examples_in_branches? ...>)
|
135
136
|
}
|
@@ -170,6 +171,7 @@ module RuboCop
|
|
170
171
|
end
|
171
172
|
|
172
173
|
def examples_in_branches?(condition_node)
|
174
|
+
return false unless condition_node
|
173
175
|
return false if !condition_node.if_type? && !condition_node.case_type?
|
174
176
|
|
175
177
|
condition_node.branches.any? { |branch| examples?(branch) }
|
@@ -55,8 +55,8 @@ module RuboCop
|
|
55
55
|
MSG_INSUFFICIENT_DESCRIPTION = 'Your example description is ' \
|
56
56
|
'insufficient.'
|
57
57
|
|
58
|
-
SHOULD_PREFIX = /\Ashould(?:n't)?\b/i.freeze
|
59
|
-
WILL_PREFIX = /\A(?:will|won't)\b/i.freeze
|
58
|
+
SHOULD_PREFIX = /\Ashould(?:n't|n’t)?\b/i.freeze
|
59
|
+
WILL_PREFIX = /\A(?:will|won't|won’t)\b/i.freeze
|
60
60
|
IT_PREFIX = /\Ait /i.freeze
|
61
61
|
|
62
62
|
# @!method it_description(node)
|
@@ -67,7 +67,6 @@ module RuboCop
|
|
67
67
|
} ...) ...)
|
68
68
|
PATTERN
|
69
69
|
|
70
|
-
# rubocop:disable Metrics/MethodLength
|
71
70
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
72
71
|
it_description(node) do |description_node, message|
|
73
72
|
if message.match?(SHOULD_PREFIX)
|
@@ -82,7 +81,6 @@ module RuboCop
|
|
82
81
|
end
|
83
82
|
end
|
84
83
|
end
|
85
|
-
# rubocop:enable Metrics/MethodLength
|
86
84
|
|
87
85
|
private
|
88
86
|
|
@@ -128,7 +126,7 @@ module RuboCop
|
|
128
126
|
node.node_parts.map { |child_node| text(child_node) }.join
|
129
127
|
when :str
|
130
128
|
node.value
|
131
|
-
|
129
|
+
else
|
132
130
|
node.source
|
133
131
|
end
|
134
132
|
end
|
@@ -65,11 +65,11 @@ module RuboCop
|
|
65
65
|
)
|
66
66
|
PATTERN
|
67
67
|
|
68
|
-
def on_send(node)
|
68
|
+
def on_send(node)
|
69
69
|
expect_literal(node) do |actual, send_node, matcher, expected|
|
70
70
|
next if SKIPPED_MATCHERS.include?(matcher)
|
71
71
|
|
72
|
-
add_offense(actual
|
72
|
+
add_offense(actual) do |corrector|
|
73
73
|
next unless CORRECTABLE_MATCHERS.include?(matcher)
|
74
74
|
next if literal?(expected)
|
75
75
|
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
|
98
98
|
def complex_literal?(node)
|
99
99
|
COMPLEX_LITERALS.include?(node.type) &&
|
100
|
-
node.each_child_node.all?
|
100
|
+
node.each_child_node.all? { |child_node| literal?(child_node) }
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
# @!method expectation(node)
|
28
28
|
def_node_search :expectation, '(send nil? #Expectations.all ...)'
|
29
29
|
|
30
|
-
def on_block(node)
|
30
|
+
def on_block(node)
|
31
31
|
return unless hook?(node)
|
32
32
|
return if node.body.nil?
|
33
33
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Do not use `expect` in let.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# let(:foo) do
|
11
|
+
# expect(something).to eq 'foo'
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# it do
|
16
|
+
# expect(something).to eq 'foo'
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
class ExpectInLet < Base
|
20
|
+
MSG = 'Do not use `%<expect>s` in let'
|
21
|
+
|
22
|
+
# @!method expectation(node)
|
23
|
+
def_node_search :expectation, '(send nil? #Expectations.all ...)'
|
24
|
+
|
25
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
26
|
+
return unless let?(node)
|
27
|
+
return if node.body.nil?
|
28
|
+
|
29
|
+
expectation(node.body) do |expect|
|
30
|
+
add_offense(expect.loc.selector, message: message(expect))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def message(expect)
|
37
|
+
format(MSG, expect: expect.method_name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -29,12 +29,6 @@ module RuboCop
|
|
29
29
|
# describe 'test' do; end
|
30
30
|
#
|
31
31
|
# # bad
|
32
|
-
# fdescribe 'test' do; end
|
33
|
-
#
|
34
|
-
# # good
|
35
|
-
# describe 'test' do; end
|
36
|
-
#
|
37
|
-
# # bad
|
38
32
|
# shared_examples 'test', focus: true do; end
|
39
33
|
#
|
40
34
|
# # good
|
@@ -81,23 +75,27 @@ module RuboCop
|
|
81
75
|
def on_send(node)
|
82
76
|
return if node.chained? || node.each_ancestor(:def, :defs).any?
|
83
77
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
correct_send(corrector, focus)
|
90
|
-
end
|
78
|
+
if focused_block?(node)
|
79
|
+
on_focused_block(node)
|
80
|
+
else
|
81
|
+
metadata(node) do |focus|
|
82
|
+
on_metadata(focus)
|
91
83
|
end
|
92
84
|
end
|
93
85
|
end
|
94
86
|
|
95
87
|
private
|
96
88
|
|
97
|
-
def
|
98
|
-
|
89
|
+
def on_focused_block(node)
|
90
|
+
add_offense(node) do |corrector|
|
91
|
+
correct_send(corrector, node)
|
92
|
+
end
|
93
|
+
end
|
99
94
|
|
100
|
-
|
95
|
+
def on_metadata(node)
|
96
|
+
add_offense(node) do |corrector|
|
97
|
+
corrector.remove(with_surrounding(node))
|
98
|
+
end
|
101
99
|
end
|
102
100
|
|
103
101
|
def with_surrounding(focus)
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
|
47
47
|
ENFORCED_REPLACEMENTS = alternatives.merge(alternatives.invert).freeze
|
48
48
|
|
49
|
-
def on_send(node)
|
49
|
+
def on_send(node)
|
50
50
|
return unless (source_range = offending_expect(node))
|
51
51
|
|
52
52
|
expectation_source = source_range.source
|
@@ -69,13 +69,13 @@ module RuboCop
|
|
69
69
|
def offending_expect(node)
|
70
70
|
case implicit_expect(node)
|
71
71
|
when :is_expected
|
72
|
-
|
72
|
+
range_for_is_expected(node.loc)
|
73
73
|
when :should, :should_not
|
74
74
|
node.loc.selector
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
78
|
+
def range_for_is_expected(source_map)
|
79
79
|
Parser::Source::Range.new(
|
80
80
|
source_map.expression.source_buffer,
|
81
81
|
source_map.expression.begin_pos,
|
@@ -107,6 +107,10 @@ module RuboCop
|
|
107
107
|
corrector.replace(node.location.selector, 'expect(subject).to')
|
108
108
|
when :should_not
|
109
109
|
corrector.replace(node.location.selector, 'expect(subject).not_to')
|
110
|
+
else
|
111
|
+
# :nocov:
|
112
|
+
:noop
|
113
|
+
# :nocov:
|
110
114
|
end
|
111
115
|
end
|
112
116
|
|
@@ -129,6 +133,10 @@ module RuboCop
|
|
129
133
|
implicit_subject_in_non_its_and_non_single_line?(node)
|
130
134
|
when :single_statement_only
|
131
135
|
implicit_subject_in_non_its_and_non_single_statement?(node)
|
136
|
+
else
|
137
|
+
# :nocov:
|
138
|
+
:noop
|
139
|
+
# :nocov:
|
132
140
|
end
|
133
141
|
end
|
134
142
|
|
@@ -48,8 +48,8 @@ module RuboCop
|
|
48
48
|
include AllowedIdentifiers
|
49
49
|
include AllowedPattern
|
50
50
|
|
51
|
-
MSG = 'This `let` statement uses index in its name.
|
52
|
-
'a meaningful name.'
|
51
|
+
MSG = 'This `let` statement uses `%<index>s` in its name. ' \
|
52
|
+
'Please give it a meaningful name.'
|
53
53
|
|
54
54
|
# @!method let_name(node)
|
55
55
|
def_node_matcher :let_name, <<~PATTERN
|
@@ -66,14 +66,17 @@ module RuboCop
|
|
66
66
|
return unless children
|
67
67
|
|
68
68
|
filter_indexed_lets(children).each do |let_node|
|
69
|
-
|
69
|
+
index = let_name(let_node)[INDEX_REGEX]
|
70
|
+
add_offense(let_node, message: format(MSG, index: index))
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
74
|
private
|
74
75
|
|
75
76
|
SUFFIX_INDEX_REGEX = /_?\d+$/.freeze
|
77
|
+
private_constant :SUFFIX_INDEX_REGEX
|
76
78
|
INDEX_REGEX = /\d+/.freeze
|
79
|
+
private_constant :INDEX_REGEX
|
77
80
|
|
78
81
|
def filter_indexed_lets(candidates)
|
79
82
|
candidates
|
@@ -45,13 +45,8 @@ module RuboCop
|
|
45
45
|
PATTERN
|
46
46
|
|
47
47
|
def on_metadata(symbols, hash)
|
48
|
-
# RSpec example groups accept two string arguments. In such a case,
|
49
|
-
# the rspec_metadata matcher will interpret the second string
|
50
|
-
# argument as a metadata symbol.
|
51
|
-
symbols.shift if symbols.first&.str_type?
|
52
|
-
|
53
48
|
symbols.each do |symbol|
|
54
|
-
on_metadata_symbol(symbol)
|
49
|
+
on_metadata_symbol(symbol) if symbol.sym_type?
|
55
50
|
end
|
56
51
|
|
57
52
|
return unless hash
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if `.to`, `not_to` or `to_not` are used.
|
7
|
+
#
|
8
|
+
# The RSpec::Expectations::ExpectationTarget must use `to`, `not_to` or
|
9
|
+
# `to_not` to run. Therefore, this cop checks if other methods are used.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# expect(something).kind_of? Foo
|
14
|
+
# is_expected == 42
|
15
|
+
# expect{something}.eq? BarError
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# expect(something).to be_a Foo
|
19
|
+
# is_expected.to eq 42
|
20
|
+
# expect{something}.to raise_error BarError
|
21
|
+
#
|
22
|
+
class MissingExpectationTargetMethod < Base
|
23
|
+
MSG = 'Use `.to`, `.not_to` or `.to_not` to set an expectation.'
|
24
|
+
RESTRICT_ON_SEND = %i[expect is_expected].freeze
|
25
|
+
|
26
|
+
# @!method expect?(node)
|
27
|
+
def_node_matcher :expect?, <<~PATTERN
|
28
|
+
{
|
29
|
+
(send nil? :expect ...)
|
30
|
+
(send nil? :is_expected)
|
31
|
+
}
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
# @!method expect_block?(node)
|
35
|
+
def_node_matcher :expect_block?, <<~PATTERN
|
36
|
+
(block #expect? (args) _body)
|
37
|
+
PATTERN
|
38
|
+
|
39
|
+
# @!method expectation_without_runner?(node)
|
40
|
+
def_node_matcher :expectation_without_runner?, <<~PATTERN
|
41
|
+
(send {#expect? #expect_block?} !#Runners.all ...)
|
42
|
+
PATTERN
|
43
|
+
|
44
|
+
def on_send(node)
|
45
|
+
node = node.parent if node.parent&.block_type?
|
46
|
+
|
47
|
+
expectation_without_runner?(node.parent) do
|
48
|
+
add_offense(node.parent.loc.selector)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -47,15 +47,12 @@ module RuboCop
|
|
47
47
|
private
|
48
48
|
|
49
49
|
def on_metadata_arguments(metadata_arguments)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
when :sym
|
56
|
-
symbols << last
|
50
|
+
if metadata_arguments.last&.hash_type?
|
51
|
+
*metadata_arguments, hash = metadata_arguments
|
52
|
+
on_metadata(metadata_arguments, hash)
|
53
|
+
else
|
54
|
+
on_metadata(metadata_arguments, nil)
|
57
55
|
end
|
58
|
-
on_metadata(symbols, hash)
|
59
56
|
end
|
60
57
|
end
|
61
58
|
end
|
@@ -7,6 +7,10 @@ module RuboCop
|
|
7
7
|
module TopLevelGroup
|
8
8
|
extend RuboCop::NodePattern::Macros
|
9
9
|
|
10
|
+
DEPRECATED_MODULE_METHOD_WARNING =
|
11
|
+
'top_level_group? is deprecated and will be ' \
|
12
|
+
'removed in the next major version of rubocop_rspec.'
|
13
|
+
|
10
14
|
def on_new_investigation
|
11
15
|
super
|
12
16
|
|
@@ -28,7 +32,10 @@ module RuboCop
|
|
28
32
|
|
29
33
|
def on_top_level_group(_node); end
|
30
34
|
|
35
|
+
# @private
|
36
|
+
# @deprecated All callers of this method have been removed.
|
31
37
|
def top_level_group?(node)
|
38
|
+
warn DEPRECATED_MODULE_METHOD_WARNING, uplevel: 1
|
32
39
|
top_level_groups.include?(node)
|
33
40
|
end
|
34
41
|
|
@@ -30,7 +30,7 @@ module RuboCop
|
|
30
30
|
|
31
31
|
def on_top_level_group(node)
|
32
32
|
top_level_example_groups =
|
33
|
-
top_level_groups.select
|
33
|
+
top_level_groups.select { |group| example_group?(group) }
|
34
34
|
|
35
35
|
return if top_level_example_groups.one?
|
36
36
|
return unless top_level_example_groups.first.equal?(node)
|
@@ -67,12 +67,12 @@ module RuboCop
|
|
67
67
|
# end
|
68
68
|
#
|
69
69
|
class MultipleExpectations < Base
|
70
|
-
include ConfigurableMax
|
71
|
-
|
72
70
|
MSG = 'Example has too many expectations [%<total>d/%<max>d].'
|
73
71
|
|
74
72
|
ANYTHING = ->(_node) { true }
|
75
|
-
|
73
|
+
TRUE_NODE = lambda(&:true_type?)
|
74
|
+
|
75
|
+
exclude_limit 'Max'
|
76
76
|
|
77
77
|
# @!method aggregate_failures?(node)
|
78
78
|
def_node_matcher :aggregate_failures?, <<~PATTERN
|
@@ -110,7 +110,7 @@ module RuboCop
|
|
110
110
|
node_with_aggregate_failures = find_aggregate_failures(example_node)
|
111
111
|
return false unless node_with_aggregate_failures
|
112
112
|
|
113
|
-
aggregate_failures?(node_with_aggregate_failures,
|
113
|
+
aggregate_failures?(node_with_aggregate_failures, TRUE_NODE)
|
114
114
|
end
|
115
115
|
|
116
116
|
def find_aggregate_failures(example_node)
|
@@ -82,11 +82,12 @@ module RuboCop
|
|
82
82
|
# end
|
83
83
|
#
|
84
84
|
class MultipleMemoizedHelpers < Base
|
85
|
-
include ConfigurableMax
|
86
85
|
include Variable
|
87
86
|
|
88
87
|
MSG = 'Example group has too many memoized helpers [%<count>d/%<max>d]'
|
89
88
|
|
89
|
+
exclude_limit 'Max'
|
90
|
+
|
90
91
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
91
92
|
return unless spec_group?(node)
|
92
93
|
|
@@ -108,10 +109,8 @@ module RuboCop
|
|
108
109
|
attr_reader :example_group_memoized_helpers
|
109
110
|
|
110
111
|
def all_helpers(node)
|
111
|
-
|
112
|
-
|
113
|
-
*node.each_ancestor(:block).flat_map(&method(:helpers))
|
114
|
-
]
|
112
|
+
helpers(node) +
|
113
|
+
node.each_ancestor(:block).flat_map { |ancestor| helpers(ancestor) }
|
115
114
|
end
|
116
115
|
|
117
116
|
def helpers(node)
|
@@ -107,8 +107,11 @@ module RuboCop
|
|
107
107
|
private
|
108
108
|
|
109
109
|
def ignored_shared_example?(node)
|
110
|
-
cop_config['IgnoreSharedExamples']
|
111
|
-
|
110
|
+
return false unless cop_config['IgnoreSharedExamples']
|
111
|
+
|
112
|
+
node.each_ancestor(:block).any? do |ancestor|
|
113
|
+
shared_example?(ancestor)
|
114
|
+
end
|
112
115
|
end
|
113
116
|
|
114
117
|
def check_explicit_subject(node)
|
@@ -92,7 +92,6 @@ module RuboCop
|
|
92
92
|
# end
|
93
93
|
#
|
94
94
|
class NestedGroups < Base
|
95
|
-
include ConfigurableMax
|
96
95
|
include TopLevelGroup
|
97
96
|
|
98
97
|
MSG = 'Maximum example group nesting exceeded [%<total>d/%<max>d].'
|
@@ -103,6 +102,8 @@ module RuboCop
|
|
103
102
|
"Configuration key `#{DEPRECATED_MAX_KEY}` for #{cop_name} is " \
|
104
103
|
'deprecated in favor of `Max`. Please use that instead.'
|
105
104
|
|
105
|
+
exclude_limit 'Max'
|
106
|
+
|
106
107
|
def on_top_level_group(node)
|
107
108
|
find_nested_example_groups(node) do |example_group, nesting|
|
108
109
|
self.max = nesting
|