rubocop-rspec 1.12.0 → 1.13.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 +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
@@ -14,37 +14,26 @@ module RuboCop
|
|
14
14
|
# expect(false).not_to be_true
|
15
15
|
# end
|
16
16
|
class NotToNot < Cop
|
17
|
-
include
|
17
|
+
include ConfigurableEnforcedStyle
|
18
18
|
|
19
|
-
MSG = 'Prefer `%s` over `%s
|
19
|
+
MSG = 'Prefer `%s` over `%s`.'.freeze
|
20
20
|
|
21
|
-
|
21
|
+
def_node_matcher :not_to_not_offense, '(send _ % ...)'
|
22
22
|
|
23
23
|
def on_send(node)
|
24
|
-
|
25
|
-
|
26
|
-
return unless METHOD_NAMES.include?(method_name)
|
27
|
-
|
28
|
-
return if style.equal?(method_name)
|
29
|
-
add_offense(node, :expression)
|
30
|
-
end
|
31
|
-
|
32
|
-
def message(node)
|
33
|
-
_receiver, method_name, *_args = *node
|
34
|
-
|
35
|
-
if method_name.equal?(:not_to)
|
36
|
-
format(MSG, 'to_not', 'not_to')
|
37
|
-
else
|
38
|
-
format(MSG, 'not_to', 'to_not')
|
24
|
+
not_to_not_offense(node, alternative_style) do
|
25
|
+
add_offense(node, :expression)
|
39
26
|
end
|
40
27
|
end
|
41
28
|
|
42
29
|
def autocorrect(node)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
30
|
+
->(corrector) { corrector.replace(node.loc.selector, style.to_s) }
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def message(_node)
|
36
|
+
format(MSG, style, alternative_style)
|
48
37
|
end
|
49
38
|
end
|
50
39
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for proper shared_context and shared_examples usage.
|
7
|
+
#
|
8
|
+
# If there are no examples defined, use shared_context.
|
9
|
+
# If there is no setup defined, use shared_examples.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# RSpec.shared_context 'only examples here' do
|
14
|
+
# it 'does x' do
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# it 'does 'y' do
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# RSpec.shared_examples 'only examples here' do
|
23
|
+
# it 'does x' do
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# it 'does 'y' do
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# # bad
|
32
|
+
# RSpec.shared_examples 'only setup here' do
|
33
|
+
# subject(:foo) { :bar }
|
34
|
+
#
|
35
|
+
# let(:baz) { :bazz }
|
36
|
+
#
|
37
|
+
# before do
|
38
|
+
# something
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# RSpec.shared_context 'only setup here' do
|
44
|
+
# subject(:foo) { :bar }
|
45
|
+
#
|
46
|
+
# let(:baz) { :bazz }
|
47
|
+
#
|
48
|
+
# before do
|
49
|
+
# something
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
class SharedContext < Cop
|
54
|
+
MSG_EXAMPLES = "Use `shared_examples` when you don't "\
|
55
|
+
'define context.'.freeze
|
56
|
+
|
57
|
+
MSG_CONTEXT = "Use `shared_context` when you don't "\
|
58
|
+
'define examples.'.freeze
|
59
|
+
|
60
|
+
examples = (Examples::ALL + Includes::EXAMPLES)
|
61
|
+
def_node_search :examples?, examples.send_pattern
|
62
|
+
|
63
|
+
context = (Hooks::ALL + Helpers::ALL + Includes::CONTEXT + Subject::ALL)
|
64
|
+
def_node_search :context?, context.send_pattern
|
65
|
+
|
66
|
+
def_node_matcher :shared_context, SharedGroups::CONTEXT.block_pattern
|
67
|
+
def_node_matcher :shared_example, SharedGroups::EXAMPLES.block_pattern
|
68
|
+
|
69
|
+
def on_block(node)
|
70
|
+
context_with_only_examples(node) do
|
71
|
+
add_shared_item_offense(node, MSG_EXAMPLES)
|
72
|
+
end
|
73
|
+
|
74
|
+
examples_with_only_context(node) do
|
75
|
+
add_shared_item_offense(node, MSG_CONTEXT)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def autocorrect(node)
|
80
|
+
lambda do |corrector|
|
81
|
+
context_with_only_examples(node.parent) do
|
82
|
+
corrector.replace(node.loc.selector, 'shared_examples')
|
83
|
+
end
|
84
|
+
|
85
|
+
examples_with_only_context(node.parent) do
|
86
|
+
corrector.replace(node.loc.selector, 'shared_context')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def context_with_only_examples(node)
|
94
|
+
shared_context(node) { yield if examples?(node) && !context?(node) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def examples_with_only_context(node)
|
98
|
+
shared_example(node) { yield if context?(node) && !examples?(node) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_shared_item_offense(node, message)
|
102
|
+
add_offense(node.children.first, :expression, message)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -15,44 +15,37 @@ module RuboCop
|
|
15
15
|
# allow(foo).to receive("bar.baz")
|
16
16
|
#
|
17
17
|
class SingleArgumentMessageChain < Cop
|
18
|
-
|
19
|
-
|
18
|
+
MSG = 'Use `%<recommended>s` instead of calling '\
|
19
|
+
'`%<called>s` with a single argument.'.freeze
|
20
|
+
|
21
|
+
def_node_matcher :message_chain, <<-PATTERN
|
22
|
+
(send _ #{Matchers::MESSAGE_CHAIN.node_pattern_union} $...)
|
23
|
+
PATTERN
|
20
24
|
|
21
25
|
def on_send(node)
|
22
|
-
|
23
|
-
|
24
|
-
return if args.size > 1
|
25
|
-
return if multi_argument_string?(args)
|
26
|
+
message_chain(node) do |(first, *remaining)|
|
27
|
+
return if first.to_s.include?('.') || remaining.any?
|
26
28
|
|
27
|
-
|
29
|
+
add_offense(node, :selector)
|
30
|
+
end
|
28
31
|
end
|
29
32
|
|
30
33
|
def autocorrect(node)
|
31
|
-
_receiver, method_name, *_args = *node
|
32
34
|
lambda do |corrector|
|
33
|
-
corrector.replace(
|
34
|
-
node.loc.selector,
|
35
|
-
method_name.equal?(:receive_message_chain) ? 'receive' : 'stub'
|
36
|
-
)
|
35
|
+
corrector.replace(node.loc.selector, replacement(node.method_name))
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
39
|
private
|
41
40
|
|
42
|
-
def
|
43
|
-
|
44
|
-
args.first.type == :str &&
|
45
|
-
args.first.children.first.include?('.')
|
41
|
+
def replacement(method)
|
42
|
+
method.equal?(:receive_message_chain) ? 'receive' : 'stub'
|
46
43
|
end
|
47
44
|
|
48
|
-
def message(
|
49
|
-
|
45
|
+
def message(node)
|
46
|
+
method = node.method_name
|
50
47
|
|
51
|
-
format(
|
52
|
-
MESSAGE,
|
53
|
-
recommended_method: recommendation,
|
54
|
-
called_method: method
|
55
|
-
)
|
48
|
+
format(MSG, recommended: replacement(method), called: method)
|
56
49
|
end
|
57
50
|
end
|
58
51
|
end
|
@@ -39,10 +39,10 @@ module RuboCop
|
|
39
39
|
#
|
40
40
|
# @yield [Symbol] subject name
|
41
41
|
def_node_matcher :subject, <<-PATTERN
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
{
|
43
|
+
(block (send nil :subject (sym $_)) args ...)
|
44
|
+
(block (send nil $:subject) args ...)
|
45
|
+
}
|
46
46
|
PATTERN
|
47
47
|
|
48
48
|
# @!method message_expectation?(node, method_name)
|
@@ -25,10 +25,11 @@ module RuboCop
|
|
25
25
|
PATTERN
|
26
26
|
|
27
27
|
def on_send(node)
|
28
|
-
|
29
|
-
|
28
|
+
unverified_double(node) do |name|
|
29
|
+
return if name.sym_type? && cop_config['IgnoreSymbolicNames']
|
30
30
|
|
31
|
-
|
31
|
+
add_offense(node, :expression)
|
32
|
+
end
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -17,7 +17,7 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# Detect if node is `before`, `after`, `around`
|
19
19
|
def_node_matcher :hook, <<-PATTERN
|
20
|
-
|
20
|
+
(block {$(send nil #{Hooks::ALL.node_pattern_union} ...)} ...)
|
21
21
|
PATTERN
|
22
22
|
|
23
23
|
def examples
|
@@ -56,20 +56,23 @@ module RuboCop
|
|
56
56
|
end
|
57
57
|
|
58
58
|
module SharedGroups
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
EXAMPLES = SelectorSet.new(%i(shared_examples shared_examples_for))
|
60
|
+
CONTEXT = SelectorSet.new(%i(shared_context))
|
61
|
+
|
62
|
+
ALL = EXAMPLES + CONTEXT
|
62
63
|
end
|
63
64
|
|
64
65
|
module Includes
|
65
|
-
|
66
|
+
EXAMPLES = SelectorSet.new(
|
66
67
|
%i(
|
67
68
|
it_behaves_like
|
68
69
|
it_should_behave_like
|
69
|
-
include_context
|
70
70
|
include_examples
|
71
71
|
)
|
72
72
|
)
|
73
|
+
CONTEXT = SelectorSet.new(%i(include_context))
|
74
|
+
|
75
|
+
ALL = EXAMPLES + CONTEXT
|
73
76
|
end
|
74
77
|
|
75
78
|
module Examples
|
@@ -82,19 +85,34 @@ module RuboCop
|
|
82
85
|
end
|
83
86
|
|
84
87
|
module Hooks
|
85
|
-
ALL = SelectorSet.new(
|
88
|
+
ALL = SelectorSet.new(
|
89
|
+
%i(
|
90
|
+
prepend_before
|
91
|
+
before
|
92
|
+
append_before
|
93
|
+
around
|
94
|
+
prepend_after
|
95
|
+
after
|
96
|
+
append_after
|
97
|
+
)
|
98
|
+
)
|
86
99
|
end
|
87
100
|
|
88
101
|
module Helpers
|
89
102
|
ALL = SelectorSet.new(%i(let let!))
|
90
103
|
end
|
91
104
|
|
105
|
+
module Subject
|
106
|
+
ALL = SelectorSet.new(%i(subject))
|
107
|
+
end
|
108
|
+
|
92
109
|
ALL =
|
93
110
|
ExampleGroups::ALL +
|
94
111
|
SharedGroups::ALL +
|
95
112
|
Examples::ALL +
|
96
113
|
Hooks::ALL +
|
97
|
-
Helpers::ALL
|
114
|
+
Helpers::ALL +
|
115
|
+
Subject::ALL
|
98
116
|
end
|
99
117
|
end
|
100
118
|
end
|
@@ -6,9 +6,9 @@ RSpec.describe ExpectViolation::Expectation do
|
|
6
6
|
context 'when given a single assertion on class end' do
|
7
7
|
let(:string) do
|
8
8
|
<<-SRC
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
class Foo
|
10
|
+
end
|
11
|
+
^^^ The end of `Foo` should be annotated.
|
12
12
|
SRC
|
13
13
|
end
|
14
14
|
|
@@ -23,7 +23,7 @@ RSpec.describe ExpectViolation::Expectation do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'has an assertion on column range 1-3' do
|
26
|
-
expect(assertion.column_range).to eql(
|
26
|
+
expect(assertion.column_range).to eql(8...11)
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'has an assertion with correct violation message' do
|
@@ -32,8 +32,8 @@ RSpec.describe ExpectViolation::Expectation do
|
|
32
32
|
|
33
33
|
it 'recreates source' do
|
34
34
|
expect(expectation.source).to eql(<<-RUBY)
|
35
|
-
|
36
|
-
|
35
|
+
class Foo
|
36
|
+
end
|
37
37
|
RUBY
|
38
38
|
end
|
39
39
|
end
|
@@ -41,13 +41,13 @@ RSpec.describe ExpectViolation::Expectation do
|
|
41
41
|
context 'when given many assertions on two lines' do
|
42
42
|
let(:string) do
|
43
43
|
<<-SRC
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
foo bar
|
45
|
+
^ Charlie
|
46
|
+
^^ Charlie
|
47
|
+
^^ Bronco
|
48
|
+
^^ Alpha
|
49
|
+
baz
|
50
|
+
^ Delta
|
51
51
|
SRC
|
52
52
|
end
|
53
53
|
|
@@ -65,7 +65,7 @@ RSpec.describe ExpectViolation::Expectation do
|
|
65
65
|
|
66
66
|
it 'has assertions on column range 1-3' do
|
67
67
|
expect(assertions.map(&:column_range)).to eql(
|
68
|
-
[
|
68
|
+
[11...13, 12...13, 12...14, 12...14, 8...9]
|
69
69
|
)
|
70
70
|
end
|
71
71
|
|
@@ -77,8 +77,8 @@ RSpec.describe ExpectViolation::Expectation do
|
|
77
77
|
|
78
78
|
it 'recreates source' do
|
79
79
|
expect(expectation.source).to eql(<<-RUBY)
|
80
|
-
|
81
|
-
|
80
|
+
foo bar
|
81
|
+
baz
|
82
82
|
RUBY
|
83
83
|
end
|
84
84
|
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
describe RuboCop::Cop::RSpec::AnyInstance do
|
1
|
+
RSpec.describe RuboCop::Cop::RSpec::AnyInstance do
|
2
2
|
subject(:cop) { described_class.new }
|
3
3
|
|
4
4
|
it 'finds `allow_any_instance_of` instead of an instance double' do
|
5
5
|
expect_violation(<<-RUBY)
|
6
6
|
before do
|
7
7
|
allow_any_instance_of(Object).to receive(:foo)
|
8
|
-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `allow_any_instance_of
|
8
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `allow_any_instance_of`.
|
9
9
|
end
|
10
10
|
RUBY
|
11
11
|
end
|
@@ -14,7 +14,7 @@ describe RuboCop::Cop::RSpec::AnyInstance do
|
|
14
14
|
expect_violation(<<-RUBY)
|
15
15
|
before do
|
16
16
|
expect_any_instance_of(Object).to receive(:foo)
|
17
|
-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `expect_any_instance_of
|
17
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `expect_any_instance_of`.
|
18
18
|
end
|
19
19
|
RUBY
|
20
20
|
end
|
@@ -23,7 +23,7 @@ describe RuboCop::Cop::RSpec::AnyInstance do
|
|
23
23
|
expect_violation(<<-RUBY)
|
24
24
|
before do
|
25
25
|
Object.any_instance.should_receive(:foo)
|
26
|
-
^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `any_instance
|
26
|
+
^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `any_instance`.
|
27
27
|
end
|
28
28
|
RUBY
|
29
29
|
end
|