rubocop-rspec 1.42.0 → 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 +17 -0
- data/config/default.yml +12 -2
- 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 +1 -1
- data/lib/rubocop/cop/rspec/base.rb +74 -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 +21 -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 +91 -7
- 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 +1 -1
- 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 +20 -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/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/subject_stub.rb +2 -2
- 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 +1 -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/language.rb +6 -4
- 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 +24 -13
- data/lib/rubocop/rspec/variable.rb +1 -1
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +23 -7
@@ -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_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,7 +16,7 @@ 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
|
@@ -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
|
@@ -15,7 +15,7 @@ module RuboCop
|
|
15
15
|
# it 'validates users' do
|
16
16
|
# expect([user1, user2, user3]).to all(be_valid)
|
17
17
|
# end
|
18
|
-
class IteratedExpectation <
|
18
|
+
class IteratedExpectation < Base
|
19
19
|
MSG = 'Prefer using the `all` matcher instead ' \
|
20
20
|
'of iterating over an array.'
|
21
21
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
# it { expect_something }
|
32
32
|
# it { expect_something_else }
|
33
33
|
#
|
34
|
-
class LeadingSubject <
|
34
|
+
class LeadingSubject < Base
|
35
35
|
extend AutoCorrector
|
36
36
|
|
37
37
|
MSG = 'Declare `subject` above any other `%<offending>s` declarations.'
|
@@ -43,33 +43,36 @@ module RuboCop
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def check_previous_nodes(node)
|
46
|
-
node
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
autocorrect(corrector, node)
|
51
|
-
end
|
46
|
+
offending_node(node) do |offender|
|
47
|
+
msg = format(MSG, offending: offender.method_name)
|
48
|
+
add_offense(node, message: msg) do |corrector|
|
49
|
+
autocorrect(corrector, node, offender)
|
52
50
|
end
|
53
|
-
|
54
|
-
break if offending?(sibling) || sibling.equal?(node)
|
55
51
|
end
|
56
52
|
end
|
57
53
|
|
58
54
|
private
|
59
55
|
|
60
|
-
def
|
61
|
-
|
56
|
+
def offending_node(node)
|
57
|
+
node.parent.each_child_node.find do |sibling|
|
58
|
+
break if sibling.equal?(node)
|
59
|
+
|
60
|
+
yield sibling if offending?(sibling)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def autocorrect(corrector, node, sibling)
|
62
65
|
RuboCop::RSpec::Corrector::MoveNode.new(
|
63
66
|
node, corrector, processed_source
|
64
|
-
).move_before(
|
67
|
+
).move_before(sibling)
|
65
68
|
end
|
66
69
|
|
67
70
|
def offending?(node)
|
68
|
-
let?(node) ||
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
let?(node) ||
|
72
|
+
hook?(node) ||
|
73
|
+
example?(node) ||
|
74
|
+
spec_group?(node) ||
|
75
|
+
include?(node)
|
73
76
|
end
|
74
77
|
|
75
78
|
def in_spec_block?(node)
|
@@ -93,7 +93,7 @@ module RuboCop
|
|
93
93
|
# stub_const('SomeModule::SomeClass', foo_class)
|
94
94
|
# end
|
95
95
|
# end
|
96
|
-
class LeakyConstantDeclaration <
|
96
|
+
class LeakyConstantDeclaration < Base
|
97
97
|
MSG_CONST = 'Stub constant instead of declaring explicitly.'
|
98
98
|
MSG_CLASS = 'Stub class constant instead of declaring explicitly.'
|
99
99
|
MSG_MODULE = 'Stub module constant instead of declaring explicitly.'
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
# it 'counts widgets' do
|
26
26
|
# expect(Widget.count).to eq(1)
|
27
27
|
# end
|
28
|
-
class LetSetup <
|
28
|
+
class LetSetup < Base
|
29
29
|
MSG = 'Do not use `let!` to setup objects not referenced in tests.'
|
30
30
|
|
31
31
|
def_node_matcher :example_or_shared_group_or_including?,
|
@@ -35,7 +35,10 @@ module RuboCop
|
|
35
35
|
).block_pattern
|
36
36
|
|
37
37
|
def_node_matcher :let_bang, <<-PATTERN
|
38
|
-
|
38
|
+
{
|
39
|
+
(block $(send nil? :let! {(sym $_) (str $_)}) ...)
|
40
|
+
$(send nil? :let! {(sym $_) (str $_)} block_pass)
|
41
|
+
}
|
39
42
|
PATTERN
|
40
43
|
|
41
44
|
def_node_search :method_called?, '(send nil? %)'
|
@@ -52,7 +55,7 @@ module RuboCop
|
|
52
55
|
|
53
56
|
def unused_let_bang(node)
|
54
57
|
child_let_bang(node) do |method_send, method_name|
|
55
|
-
yield(method_send) unless method_called?(node, method_name)
|
58
|
+
yield(method_send) unless method_called?(node, method_name.to_sym)
|
56
59
|
end
|
57
60
|
end
|
58
61
|
|