rubocop-rspec 1.42.0 → 1.44.1
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 +44 -2
- data/config/default.yml +41 -3
- data/lib/rubocop-rspec.rb +2 -1
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +1 -1
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +1 -1
- data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
- data/lib/rubocop/cop/rspec/around_block.rb +2 -2
- data/lib/rubocop/cop/rspec/base.rb +76 -0
- data/lib/rubocop/cop/rspec/be.rb +1 -1
- data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
- data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +6 -3
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/context_method.rb +2 -2
- data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
- data/lib/rubocop/cop/rspec/cop.rb +2 -66
- data/lib/rubocop/cop/rspec/describe_class.rb +40 -30
- data/lib/rubocop/cop/rspec/describe_method.rb +14 -6
- data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
- data/lib/rubocop/cop/rspec/described_class.rb +2 -2
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
- data/lib/rubocop/cop/rspec/dialect.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_example_group.rb +124 -6
- data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +4 -8
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +4 -8
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +7 -10
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +4 -8
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +5 -8
- 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 +4 -4
- data/lib/rubocop/cop/rspec/expect_actual.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_change.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +3 -3
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +10 -6
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -1
- data/lib/rubocop/cop/rspec/file_path.rb +25 -17
- data/lib/rubocop/cop/rspec/focus.rb +7 -11
- data/lib/rubocop/cop/rspec/hook_argument.rb +5 -6
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -3
- data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_subject.rb +8 -6
- data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +1 -1
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/leading_subject.rb +24 -17
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/let_setup.rb +6 -3
- data/lib/rubocop/cop/rspec/message_chain.rb +1 -1
- data/lib/rubocop/cop/rspec/message_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/message_spies.rb +1 -1
- 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 +1 -1
- data/lib/rubocop/cop/rspec/named_subject.rb +1 -1
- data/lib/rubocop/cop/rspec/nested_groups.rb +4 -4
- data/lib/rubocop/cop/rspec/not_to_not.rb +1 -1
- 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 +7 -14
- data/lib/rubocop/cop/rspec/rails/http_status.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_never.rb +2 -2
- 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 +1 -1
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +103 -0
- data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
- data/lib/rubocop/cop/rspec/scattered_let.rb +1 -1
- data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +1 -1
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +172 -0
- data/lib/rubocop/cop/rspec/subject_stub.rb +6 -6
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +6 -6
- data/lib/rubocop/cop/rspec/variable_name.rb +28 -9
- 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 +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +3 -0
- data/lib/rubocop/rspec/corrector/move_node.rb +7 -5
- data/lib/rubocop/rspec/description_extractor.rb +1 -1
- data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -2
- data/lib/rubocop/rspec/example_group.rb +2 -2
- data/lib/rubocop/rspec/hook.rb +1 -5
- data/lib/rubocop/rspec/language.rb +12 -5
- data/lib/rubocop/rspec/language/node_pattern.rb +6 -1
- data/lib/rubocop/rspec/top_level_describe.rb +2 -2
- data/lib/rubocop/rspec/top_level_group.rb +26 -13
- data/lib/rubocop/rspec/variable.rb +1 -1
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +38 -6
@@ -14,20 +14,17 @@ module RuboCop
|
|
14
14
|
# subject(:obj) { described_class }
|
15
15
|
#
|
16
16
|
# let(:foo) { bar }
|
17
|
-
class EmptyLineAfterSubject <
|
17
|
+
class EmptyLineAfterSubject < Base
|
18
18
|
extend AutoCorrector
|
19
|
-
include RuboCop::RSpec::
|
19
|
+
include RuboCop::RSpec::EmptyLineSeparation
|
20
20
|
|
21
|
-
MSG = 'Add empty line after
|
21
|
+
MSG = 'Add an empty line after `%<subject>s`.'
|
22
22
|
|
23
23
|
def on_block(node)
|
24
24
|
return unless subject?(node) && !in_spec_block?(node)
|
25
|
-
return if last_child?(node)
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
corrector.insert_after(location.end, "\n")
|
30
|
-
end
|
26
|
+
missing_separating_line_offense(node) do |method|
|
27
|
+
format(MSG, subject: method)
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
# result = service.call
|
48
48
|
# expect(result).to be(true)
|
49
49
|
# end
|
50
|
-
class ExampleWithoutDescription <
|
50
|
+
class ExampleWithoutDescription < Base
|
51
51
|
include ConfigurableEnforcedStyle
|
52
52
|
|
53
53
|
MSG_DEFAULT_ARGUMENT = 'Omit the argument when you want to ' \
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
# # good
|
30
30
|
# it 'does things' do
|
31
31
|
# end
|
32
|
-
class ExampleWording <
|
32
|
+
class ExampleWording < Base
|
33
33
|
extend AutoCorrector
|
34
34
|
|
35
35
|
MSG_SHOULD = 'Do not use should when describing your tests.'
|
@@ -47,9 +47,9 @@ module RuboCop
|
|
47
47
|
|
48
48
|
def on_block(node)
|
49
49
|
it_description(node) do |description_node, message|
|
50
|
-
if message
|
50
|
+
if message.match?(SHOULD_PREFIX)
|
51
51
|
add_wording_offense(description_node, MSG_SHOULD)
|
52
|
-
elsif message
|
52
|
+
elsif message.match?(IT_PREFIX)
|
53
53
|
add_wording_offense(description_node, MSG_IT)
|
54
54
|
end
|
55
55
|
end
|
@@ -77,7 +77,7 @@ module RuboCop
|
|
77
77
|
def replacement_text(node)
|
78
78
|
text = text(node)
|
79
79
|
|
80
|
-
if text
|
80
|
+
if text.match?(SHOULD_PREFIX)
|
81
81
|
RuboCop::RSpec::Wording.new(
|
82
82
|
text,
|
83
83
|
ignore: ignored_words,
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
#
|
25
25
|
# # good
|
26
26
|
# count { 1 }
|
27
|
-
class AttributeDefinedStatically <
|
27
|
+
class AttributeDefinedStatically < Base
|
28
28
|
extend AutoCorrector
|
29
29
|
|
30
30
|
MSG = 'Use a block to declare attribute values.'
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
39
39
|
|
40
40
|
def on_block(node)
|
41
41
|
attributes = factory_attributes(node) || []
|
42
|
-
attributes = [attributes] unless attributes.is_a?(Array)
|
42
|
+
attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective
|
43
43
|
|
44
44
|
attributes.each do |attribute|
|
45
45
|
next unless offensive_receiver?(attribute.receiver, node)
|
@@ -84,7 +84,7 @@ module RuboCop
|
|
84
84
|
def autocorrect_replacing_parens(corrector, node)
|
85
85
|
left_braces, right_braces = braces(node)
|
86
86
|
|
87
|
-
corrector.replace(node.location.begin,
|
87
|
+
corrector.replace(node.location.begin, " #{left_braces}")
|
88
88
|
corrector.replace(node.location.end, right_braces)
|
89
89
|
end
|
90
90
|
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
#
|
25
25
|
# # good
|
26
26
|
# 3.times { create :user }
|
27
|
-
class CreateList <
|
27
|
+
class CreateList < Base
|
28
28
|
extend AutoCorrector
|
29
29
|
include ConfigurableEnforcedStyle
|
30
30
|
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
PATTERN
|
45
45
|
|
46
46
|
def_node_matcher :factory_list_call, <<-PATTERN
|
47
|
-
(send
|
47
|
+
(send {(const nil? {:FactoryGirl :FactoryBot}) nil?} :create_list (sym _) (int $_) ...)
|
48
48
|
PATTERN
|
49
49
|
|
50
50
|
def on_block(node)
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
60
60
|
def on_send(node)
|
61
61
|
return unless style == :n_times
|
62
62
|
|
63
|
-
factory_list_call(node) do |
|
63
|
+
factory_list_call(node) do |count|
|
64
64
|
message = format(MSG_N_TIMES, number: count)
|
65
65
|
add_offense(node.loc.selector, message: message) do |corrector|
|
66
66
|
TimesCorrector.new(node).call(corrector)
|
@@ -79,7 +79,7 @@ module RuboCop
|
|
79
79
|
end
|
80
80
|
|
81
81
|
# :nodoc
|
82
|
-
|
82
|
+
module Corrector
|
83
83
|
private
|
84
84
|
|
85
85
|
def build_options_string(options)
|
@@ -102,7 +102,9 @@ module RuboCop
|
|
102
102
|
end
|
103
103
|
|
104
104
|
# :nodoc
|
105
|
-
class TimesCorrector
|
105
|
+
class TimesCorrector
|
106
|
+
include Corrector
|
107
|
+
|
106
108
|
def initialize(node)
|
107
109
|
@node = node
|
108
110
|
end
|
@@ -130,7 +132,9 @@ module RuboCop
|
|
130
132
|
end
|
131
133
|
|
132
134
|
# :nodoc:
|
133
|
-
class CreateListCorrector
|
135
|
+
class CreateListCorrector
|
136
|
+
include Corrector
|
137
|
+
|
134
138
|
def initialize(node)
|
135
139
|
@node = node.parent
|
136
140
|
end
|
@@ -56,35 +56,43 @@ module RuboCop
|
|
56
56
|
# # good
|
57
57
|
# my_class_spec.rb # describe MyClass, '#method'
|
58
58
|
#
|
59
|
-
class FilePath <
|
60
|
-
include RuboCop::RSpec::
|
59
|
+
class FilePath < Base
|
60
|
+
include RuboCop::RSpec::TopLevelGroup
|
61
61
|
|
62
62
|
MSG = 'Spec path should end with `%<suffix>s`.'
|
63
63
|
|
64
|
-
|
64
|
+
def_node_matcher :const_described, <<~PATTERN
|
65
|
+
(block
|
66
|
+
$(send #rspec? _example_group $(const ...) $...) ...
|
67
|
+
)
|
68
|
+
PATTERN
|
69
|
+
|
65
70
|
def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))'
|
66
71
|
|
67
|
-
def
|
68
|
-
return unless
|
69
|
-
return if routing_spec?(args)
|
72
|
+
def on_top_level_example_group(node)
|
73
|
+
return unless top_level_groups.one?
|
70
74
|
|
71
|
-
|
75
|
+
const_described(node) do |send_node, described_class, arguments|
|
76
|
+
next if routing_spec?(arguments)
|
72
77
|
|
73
|
-
|
74
|
-
|
75
|
-
add_offense(
|
76
|
-
node,
|
77
|
-
message: format(MSG, suffix: glob)
|
78
|
-
)
|
78
|
+
ensure_correct_file_path(send_node, described_class, arguments)
|
79
|
+
end
|
79
80
|
end
|
80
81
|
|
81
82
|
private
|
82
83
|
|
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))
|
89
|
+
end
|
90
|
+
|
83
91
|
def routing_spec?(args)
|
84
92
|
args.any?(&method(:routing_metadata?))
|
85
93
|
end
|
86
94
|
|
87
|
-
def glob_for(
|
95
|
+
def glob_for(described_class, method_name)
|
88
96
|
return glob_for_spec_suffix_only? if spec_suffix_only?
|
89
97
|
|
90
98
|
"#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
|
@@ -94,10 +102,10 @@ module RuboCop
|
|
94
102
|
'*_spec.rb'
|
95
103
|
end
|
96
104
|
|
97
|
-
def name_glob(
|
98
|
-
return unless
|
105
|
+
def name_glob(method_name)
|
106
|
+
return unless method_name&.str_type?
|
99
107
|
|
100
|
-
"*#{
|
108
|
+
"*#{method_name.str_content.gsub(/\W/, '')}" unless ignore_methods?
|
101
109
|
end
|
102
110
|
|
103
111
|
def expected_path(constant)
|
@@ -19,23 +19,19 @@ module RuboCop
|
|
19
19
|
# # good
|
20
20
|
# describe MyClass do
|
21
21
|
# end
|
22
|
-
class Focus <
|
22
|
+
class Focus < Base
|
23
23
|
MSG = 'Focused spec found.'
|
24
24
|
|
25
|
-
focusable =
|
26
|
-
ExampleGroups::GROUPS +
|
27
|
-
ExampleGroups::SKIPPED +
|
28
|
-
Examples::EXAMPLES +
|
29
|
-
Examples::SKIPPED +
|
30
|
-
Examples::PENDING
|
31
|
-
|
32
25
|
focused = ExampleGroups::FOCUSED + Examples::FOCUSED
|
33
26
|
|
34
|
-
|
27
|
+
def_node_matcher :focusable_selector?,
|
28
|
+
(ExampleGroups::GROUPS + ExampleGroups::SKIPPED +
|
29
|
+
Examples::EXAMPLES + Examples::SKIPPED +
|
30
|
+
Examples::PENDING).node_pattern_union
|
35
31
|
|
36
32
|
def_node_matcher :metadata, <<-PATTERN
|
37
|
-
{(send #
|
38
|
-
(send #
|
33
|
+
{(send #rspec? #focusable_selector? <$(sym :focus) ...>)
|
34
|
+
(send #rspec? #focusable_selector? ... (hash <$(pair (sym :focus) true) ...>))}
|
39
35
|
PATTERN
|
40
36
|
|
41
37
|
def_node_matcher :focused_block?, focused.send_pattern
|
@@ -57,21 +57,20 @@ module RuboCop
|
|
57
57
|
# before(:example) do
|
58
58
|
# # ...
|
59
59
|
# end
|
60
|
-
class HookArgument <
|
60
|
+
class HookArgument < Base
|
61
61
|
extend AutoCorrector
|
62
62
|
include ConfigurableEnforcedStyle
|
63
63
|
|
64
|
-
IMPLICIT_MSG = 'Omit the default `%<scope>p` '
|
65
|
-
'argument for RSpec hooks.'
|
64
|
+
IMPLICIT_MSG = 'Omit the default `%<scope>p` argument for RSpec hooks.'
|
66
65
|
EXPLICIT_MSG = 'Use `%<scope>p` for RSpec hooks.'
|
67
66
|
|
68
|
-
|
67
|
+
def_node_matcher :hook?, Hooks::ALL.node_pattern_union
|
69
68
|
|
70
69
|
def_node_matcher :scoped_hook, <<-PATTERN
|
71
|
-
(block $(send _ #
|
70
|
+
(block $(send _ #hook? (sym ${:each :example})) ...)
|
72
71
|
PATTERN
|
73
72
|
|
74
|
-
def_node_matcher :unscoped_hook,
|
73
|
+
def_node_matcher :unscoped_hook, '(block $(send _ #hook?) ...)'
|
75
74
|
|
76
75
|
def on_block(node)
|
77
76
|
hook(node) do |method_send, scope_name|
|
@@ -16,14 +16,13 @@ module RuboCop
|
|
16
16
|
# it 'changes something to a new value' do
|
17
17
|
# expect { do_something }.to change(something).to(new_value)
|
18
18
|
# end
|
19
|
-
class ImplicitBlockExpectation <
|
19
|
+
class ImplicitBlockExpectation < Base
|
20
20
|
MSG = 'Avoid implicit block expectations.'
|
21
21
|
|
22
22
|
def_node_matcher :lambda?, <<-PATTERN
|
23
23
|
{
|
24
24
|
(send (const nil? :Proc) :new)
|
25
|
-
(send nil? :proc)
|
26
|
-
(send nil? :lambda)
|
25
|
+
(send nil? {:proc :lambda})
|
27
26
|
}
|
28
27
|
PATTERN
|
29
28
|
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
26
26
|
# # good
|
27
27
|
# it { expect(subject).to be_truthy }
|
28
28
|
#
|
29
|
-
class ImplicitSubject <
|
29
|
+
class ImplicitSubject < Base
|
30
30
|
extend AutoCorrector
|
31
31
|
include ConfigurableEnforcedStyle
|
32
32
|
|
@@ -49,9 +49,10 @@ module RuboCop
|
|
49
49
|
|
50
50
|
def autocorrect(corrector, node)
|
51
51
|
replacement = 'expect(subject)'
|
52
|
-
|
52
|
+
case node.method_name
|
53
|
+
when :should
|
53
54
|
replacement += '.to'
|
54
|
-
|
55
|
+
when :should_not
|
55
56
|
replacement += '.not_to'
|
56
57
|
end
|
57
58
|
|
@@ -62,13 +63,14 @@ module RuboCop
|
|
62
63
|
example = node.ancestors.find { |parent| example?(parent) }
|
63
64
|
return false if example.nil?
|
64
65
|
|
65
|
-
example.
|
66
|
+
example.method?(:its) || allowed_by_style?(example)
|
66
67
|
end
|
67
68
|
|
68
69
|
def allowed_by_style?(example)
|
69
|
-
|
70
|
+
case style
|
71
|
+
when :single_line_only
|
70
72
|
example.single_line?
|
71
|
-
|
73
|
+
when :single_statement_only
|
72
74
|
!example.body.begin_type?
|
73
75
|
else
|
74
76
|
false
|