rubocop-rspec 2.11.1 → 2.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 +125 -81
- data/config/default.yml +59 -6
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +8 -9
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +8 -9
- data/lib/rubocop/cop/rspec/any_instance.rb +1 -0
- data/lib/rubocop/cop/rspec/around_block.rb +26 -3
- data/lib/rubocop/cop/rspec/be.rb +0 -1
- data/lib/rubocop/cop/rspec/be_eq.rb +0 -1
- data/lib/rubocop/cop/rspec/be_eql.rb +0 -1
- data/lib/rubocop/cop/rspec/before_after_all.rb +1 -0
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +9 -3
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +2 -1
- data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +86 -0
- data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +158 -0
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +0 -1
- data/lib/rubocop/cop/rspec/change_by_zero.rb +67 -7
- data/lib/rubocop/cop/rspec/class_check.rb +101 -0
- data/lib/rubocop/cop/rspec/context_method.rb +2 -1
- data/lib/rubocop/cop/rspec/context_wording.rb +49 -18
- data/lib/rubocop/cop/rspec/describe_class.rb +1 -1
- data/lib/rubocop/cop/rspec/describe_method.rb +1 -0
- data/lib/rubocop/cop/rspec/described_class.rb +5 -15
- data/lib/rubocop/cop/rspec/dialect.rb +1 -0
- data/lib/rubocop/cop/rspec/empty_example_group.rb +19 -4
- data/lib/rubocop/cop/rspec/empty_hook.rb +4 -5
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +4 -9
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +2 -1
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +32 -2
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +2 -1
- data/lib/rubocop/cop/rspec/example_length.rb +3 -2
- data/lib/rubocop/cop/rspec/example_without_description.rb +3 -2
- data/lib/rubocop/cop/rspec/example_wording.rb +2 -1
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -0
- data/lib/rubocop/cop/rspec/expect_actual.rb +5 -0
- data/lib/rubocop/cop/rspec/expect_change.rb +9 -9
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +4 -1
- data/lib/rubocop/cop/rspec/expect_output.rb +1 -0
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +2 -1
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +50 -13
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -0
- data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +1 -1
- data/lib/rubocop/cop/rspec/file_path.rb +8 -4
- data/lib/rubocop/cop/rspec/focus.rb +20 -4
- data/lib/rubocop/cop/rspec/hook_argument.rb +10 -5
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +10 -9
- data/lib/rubocop/cop/rspec/identical_equality_assertion.rb +0 -1
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -0
- data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -3
- data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
- data/lib/rubocop/cop/rspec/instance_variable.rb +0 -1
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +3 -2
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +16 -0
- data/lib/rubocop/cop/rspec/leading_subject.rb +15 -15
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +7 -8
- data/lib/rubocop/cop/rspec/let_setup.rb +4 -4
- 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 +7 -1
- data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +2 -1
- data/lib/rubocop/cop/rspec/mixin/css_selector.rb +99 -0
- data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +13 -4
- data/lib/rubocop/cop/rspec/mixin/namespace.rb +23 -0
- data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -0
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +19 -3
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +1 -3
- data/lib/rubocop/cop/rspec/multiple_subjects.rb +17 -2
- data/lib/rubocop/cop/rspec/named_subject.rb +2 -1
- data/lib/rubocop/cop/rspec/nested_groups.rb +45 -25
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +64 -0
- data/lib/rubocop/cop/rspec/not_to_not.rb +13 -1
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +2 -1
- data/lib/rubocop/cop/rspec/pending.rb +1 -0
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +2 -1
- data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +1 -2
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +47 -0
- data/lib/rubocop/cop/rspec/receive_counts.rb +14 -15
- data/lib/rubocop/cop/rspec/receive_never.rb +4 -5
- data/lib/rubocop/cop/rspec/repeated_description.rb +25 -26
- data/lib/rubocop/cop/rspec/repeated_example.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +28 -29
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +28 -29
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +32 -33
- data/lib/rubocop/cop/rspec/return_from_stub.rb +12 -12
- data/lib/rubocop/cop/rspec/scattered_let.rb +1 -5
- data/lib/rubocop/cop/rspec/scattered_setup.rb +2 -2
- data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +0 -1
- data/lib/rubocop/cop/rspec/subject_declaration.rb +0 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +2 -2
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +15 -15
- data/lib/rubocop/cop/rspec/variable_definition.rb +1 -0
- data/lib/rubocop/cop/rspec/variable_name.rb +6 -7
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -0
- data/lib/rubocop/cop/rspec/void_expect.rb +2 -1
- data/lib/rubocop/cop/rspec/yield.rb +3 -2
- data/lib/rubocop/cop/rspec_cops.rb +5 -0
- data/lib/rubocop/rspec/config_formatter.rb +14 -3
- data/lib/rubocop/rspec/inject.rb +1 -3
- data/lib/rubocop/rspec/language/node_pattern.rb +4 -0
- data/lib/rubocop/rspec/language.rb +6 -1
- data/lib/rubocop/rspec/node.rb +1 -1
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop/rspec/wording.rb +2 -2
- data/lib/rubocop/rspec.rb +14 -0
- data/lib/rubocop-rspec.rb +3 -0
- metadata +12 -88
@@ -6,7 +6,6 @@ module RuboCop
|
|
6
6
|
# Checks if an example group defines `subject` multiple times.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
-
#
|
10
9
|
# # bad
|
11
10
|
# describe Foo do
|
12
11
|
# subject(:user) { User.new }
|
@@ -19,6 +18,21 @@ module RuboCop
|
|
19
18
|
# subject(:post) { Post.new }
|
20
19
|
# end
|
21
20
|
#
|
21
|
+
# # bad (does not support autocorrection)
|
22
|
+
# describe Foo do
|
23
|
+
# subject!(:user) { User.new }
|
24
|
+
# subject!(:post) { Post.new }
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# describe Foo do
|
29
|
+
# before do
|
30
|
+
# User.new
|
31
|
+
# Post.new
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# This cop does not support autocorrection in some cases.
|
22
36
|
# The autocorrect behavior for this cop depends on the type of
|
23
37
|
# duplication:
|
24
38
|
#
|
@@ -33,13 +47,14 @@ module RuboCop
|
|
33
47
|
# - If subjects are defined with `subject!` then we don't autocorrect.
|
34
48
|
# This is enough of an edge case that people can just move this to
|
35
49
|
# a `before` hook on their own
|
50
|
+
#
|
36
51
|
class MultipleSubjects < Base
|
37
52
|
extend AutoCorrector
|
38
53
|
include RangeHelp
|
39
54
|
|
40
55
|
MSG = 'Do not set more than one subject per example group'
|
41
56
|
|
42
|
-
def on_block(node)
|
57
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
43
58
|
return unless example_group?(node)
|
44
59
|
|
45
60
|
subjects = RuboCop::RSpec::ExampleGroup.new(node).subjects
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
41
41
|
#
|
42
42
|
# it { is_expected.to be_valid }
|
43
43
|
# end
|
44
|
+
#
|
44
45
|
class NamedSubject < Base
|
45
46
|
MSG = 'Name your test subject if you need to reference it explicitly.'
|
46
47
|
|
@@ -55,7 +56,7 @@ module RuboCop
|
|
55
56
|
# @!method subject_usage(node)
|
56
57
|
def_node_search :subject_usage, '$(send nil? :subject)'
|
57
58
|
|
58
|
-
def on_block(node)
|
59
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
59
60
|
if !example_or_hook_block?(node) || ignored_shared_example?(node)
|
60
61
|
return
|
61
62
|
end
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
# end
|
37
37
|
# end
|
38
38
|
#
|
39
|
-
# #
|
39
|
+
# # good
|
40
40
|
# context 'using some feature as an admin' do
|
41
41
|
# let(:some) { :various }
|
42
42
|
# let(:feature) { :setup }
|
@@ -53,34 +53,40 @@ module RuboCop
|
|
53
53
|
# it 'yada yada'
|
54
54
|
# end
|
55
55
|
#
|
56
|
-
# @example
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
# let(:some) { :various }
|
64
|
-
# let(:feature) { :setup }
|
65
|
-
#
|
66
|
-
# context 'when user is signed in' do
|
67
|
-
# let(:user) do
|
68
|
-
# UserCreate.call(user_attributes)
|
56
|
+
# @example `Max: 3` (default)
|
57
|
+
# # bad
|
58
|
+
# describe Foo do
|
59
|
+
# context 'foo' do
|
60
|
+
# context 'bar' do
|
61
|
+
# context 'baz' do # flagged by rubocop
|
62
|
+
# end
|
69
63
|
# end
|
64
|
+
# end
|
65
|
+
# end
|
70
66
|
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
67
|
+
# @example `Max: 2`
|
68
|
+
# # bad
|
69
|
+
# describe Foo do
|
70
|
+
# context 'foo' do
|
71
|
+
# context 'bar' do # flagged by rubocop
|
72
|
+
# context 'baz' do # flagged by rubocop
|
73
|
+
# end
|
77
74
|
# end
|
75
|
+
# end
|
76
|
+
# end
|
78
77
|
#
|
79
|
-
#
|
80
|
-
#
|
78
|
+
# @example `AllowedGroups: [] (default)`
|
79
|
+
# describe Foo do # <-- nested groups 1
|
80
|
+
# context 'foo' do # <-- nested groups 2
|
81
|
+
# context 'bar' do # <-- nested groups 3
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
# end
|
81
85
|
#
|
82
|
-
#
|
83
|
-
#
|
86
|
+
# @example `AllowedGroups: [path]`
|
87
|
+
# describe Foo do # <-- nested groups 1
|
88
|
+
# path '/foo' do # <-- nested groups 1 (not counted)
|
89
|
+
# context 'bar' do # <-- nested groups 2
|
84
90
|
# end
|
85
91
|
# end
|
86
92
|
# end
|
@@ -113,13 +119,23 @@ module RuboCop
|
|
113
119
|
example_group = example_group?(node)
|
114
120
|
yield node, nesting if example_group && nesting > max_nesting
|
115
121
|
|
116
|
-
next_nesting =
|
122
|
+
next_nesting = if count_up_nesting?(node, example_group)
|
123
|
+
nesting + 1
|
124
|
+
else
|
125
|
+
nesting
|
126
|
+
end
|
117
127
|
|
118
128
|
node.each_child_node(:block, :begin) do |child|
|
119
129
|
find_nested_example_groups(child, nesting: next_nesting, &block)
|
120
130
|
end
|
121
131
|
end
|
122
132
|
|
133
|
+
def count_up_nesting?(node, example_group)
|
134
|
+
example_group &&
|
135
|
+
(node.block_type? &&
|
136
|
+
!allowed_groups.include?(node.method_name))
|
137
|
+
end
|
138
|
+
|
123
139
|
def message(nesting)
|
124
140
|
format(MSG, total: nesting, max: max_nesting)
|
125
141
|
end
|
@@ -136,6 +152,10 @@ module RuboCop
|
|
136
152
|
cop_config.fetch('Max', 3)
|
137
153
|
end
|
138
154
|
end
|
155
|
+
|
156
|
+
def allowed_groups
|
157
|
+
@allowed_groups ||= cop_config.fetch('AllowedGroups', [])
|
158
|
+
end
|
139
159
|
end
|
140
160
|
end
|
141
161
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if an example contains any expectation.
|
7
|
+
#
|
8
|
+
# All RSpec's example and expectation methods are covered by default.
|
9
|
+
# If you are using your own custom methods,
|
10
|
+
# add the following configuration:
|
11
|
+
#
|
12
|
+
# RSpec:
|
13
|
+
# Language:
|
14
|
+
# Examples:
|
15
|
+
# Regular:
|
16
|
+
# - custom_it
|
17
|
+
# Expectations:
|
18
|
+
# - custom_expect
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# # bad
|
22
|
+
# it do
|
23
|
+
# a?
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# it do
|
28
|
+
# expect(a?).to be(true)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
class NoExpectationExample < Base
|
32
|
+
MSG = 'No expectation found in this example.'
|
33
|
+
|
34
|
+
# @!method regular_or_focused_example?(node)
|
35
|
+
# @param [RuboCop::AST::Node] node
|
36
|
+
# @return [Boolean]
|
37
|
+
def_node_matcher :regular_or_focused_example?, <<~PATTERN
|
38
|
+
{
|
39
|
+
#{block_pattern('{#Examples.regular | #Examples.focused}')}
|
40
|
+
#{numblock_pattern('{#Examples.regular | #Examples.focused}')}
|
41
|
+
}
|
42
|
+
PATTERN
|
43
|
+
|
44
|
+
# @!method including_any_expectation?(node)
|
45
|
+
# @param [RuboCop::AST::Node] node
|
46
|
+
# @return [Boolean]
|
47
|
+
def_node_search(
|
48
|
+
:including_any_expectation?,
|
49
|
+
send_pattern('#Expectations.all')
|
50
|
+
)
|
51
|
+
|
52
|
+
# @param [RuboCop::AST::BlockNode] node
|
53
|
+
def on_block(node)
|
54
|
+
return unless regular_or_focused_example?(node)
|
55
|
+
return if including_any_expectation?(node)
|
56
|
+
|
57
|
+
add_offense(node)
|
58
|
+
end
|
59
|
+
|
60
|
+
alias on_numblock on_block
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module RSpec
|
6
6
|
# Checks for consistent method usage for negating expectations.
|
7
7
|
#
|
8
|
-
# @example
|
8
|
+
# @example `EnforcedStyle: not_to` (default)
|
9
9
|
# # bad
|
10
10
|
# it '...' do
|
11
11
|
# expect(false).to_not be_true
|
@@ -15,6 +15,18 @@ module RuboCop
|
|
15
15
|
# it '...' do
|
16
16
|
# expect(false).not_to be_true
|
17
17
|
# end
|
18
|
+
#
|
19
|
+
# @example `EnforcedStyle: to_not`
|
20
|
+
# # bad
|
21
|
+
# it '...' do
|
22
|
+
# expect(false).not_to be_true
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# it '...' do
|
27
|
+
# expect(false).to_not be_true
|
28
|
+
# end
|
29
|
+
#
|
18
30
|
class NotToNot < Base
|
19
31
|
extend AutoCorrector
|
20
32
|
include ConfigurableEnforcedStyle
|
@@ -21,6 +21,7 @@ module RuboCop
|
|
21
21
|
# let(:foo) { bar }
|
22
22
|
# let(:baz) { baz }
|
23
23
|
# let!(:other) { other }
|
24
|
+
#
|
24
25
|
class OverwritingSetup < Base
|
25
26
|
MSG = '`%<name>s` is already defined.'
|
26
27
|
|
@@ -30,7 +31,7 @@ module RuboCop
|
|
30
31
|
# @!method first_argument_name(node)
|
31
32
|
def_node_matcher :first_argument_name, '(send _ _ ({str sym} $_))'
|
32
33
|
|
33
|
-
def on_block(node)
|
34
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
34
35
|
return unless example_group_with_body?(node)
|
35
36
|
|
36
37
|
find_duplicates(node.body) do |duplicate, name|
|
@@ -276,6 +276,7 @@ module RuboCop
|
|
276
276
|
#
|
277
277
|
# # good - the above code is rewritten to it by this cop
|
278
278
|
# expect(foo.something?).to be_truthy
|
279
|
+
#
|
279
280
|
class PredicateMatcher < Base
|
280
281
|
extend AutoCorrector
|
281
282
|
include ConfigurableEnforcedStyle
|
@@ -291,7 +292,7 @@ module RuboCop
|
|
291
292
|
end
|
292
293
|
end
|
293
294
|
|
294
|
-
def on_block(node)
|
295
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
295
296
|
check_explicit(node) if style == :explicit
|
296
297
|
end
|
297
298
|
|
@@ -7,7 +7,6 @@ module RuboCop
|
|
7
7
|
# Checks that tests use RSpec `before` hook over Rails `setup` method.
|
8
8
|
#
|
9
9
|
# @example
|
10
|
-
#
|
11
10
|
# # bad
|
12
11
|
# setup do
|
13
12
|
# allow(foo).to receive(:bar)
|
@@ -30,7 +29,7 @@ module RuboCop
|
|
30
29
|
(args) _)
|
31
30
|
PATTERN
|
32
31
|
|
33
|
-
def on_block(node)
|
32
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
34
33
|
setup_call(node) do |setup|
|
35
34
|
add_offense(node) do |corrector|
|
36
35
|
corrector.replace setup, 'before'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
module Rails
|
7
|
+
# Checks that tests use `have_http_status` instead of equality matchers.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# expect(response.status).to be(200)
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# expect(response).to have_http_status(200)
|
15
|
+
#
|
16
|
+
class HaveHttpStatus < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
19
|
+
MSG =
|
20
|
+
'Prefer `expect(response).%<to>s have_http_status(%<status>i)` ' \
|
21
|
+
'over `expect(response.status).%<to>s %<match>s`.'
|
22
|
+
|
23
|
+
# @!method match_status(node)
|
24
|
+
def_node_matcher :match_status, <<-PATTERN
|
25
|
+
(send
|
26
|
+
(send nil? :expect
|
27
|
+
$(send (send nil? :response) :status)
|
28
|
+
)
|
29
|
+
$#Runners.all
|
30
|
+
$(send nil? {:be :eq :eql :equal} (int $_))
|
31
|
+
)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_send(node)
|
35
|
+
match_status(node) do |response_status, to, match, status|
|
36
|
+
message = format(MSG, to: to, match: match.source, status: status)
|
37
|
+
add_offense(node, message: message) do |corrector|
|
38
|
+
corrector.replace(response_status.source_range, 'response')
|
39
|
+
corrector.replace(match.loc.selector, 'have_http_status')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -6,22 +6,21 @@ module RuboCop
|
|
6
6
|
# Check for `once` and `twice` receive counts matchers usage.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
+
# # bad
|
10
|
+
# expect(foo).to receive(:bar).exactly(1).times
|
11
|
+
# expect(foo).to receive(:bar).exactly(2).times
|
12
|
+
# expect(foo).to receive(:bar).at_least(1).times
|
13
|
+
# expect(foo).to receive(:bar).at_least(2).times
|
14
|
+
# expect(foo).to receive(:bar).at_most(1).times
|
15
|
+
# expect(foo).to receive(:bar).at_most(2).times
|
9
16
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# # good
|
19
|
-
# expect(foo).to receive(:bar).once
|
20
|
-
# expect(foo).to receive(:bar).twice
|
21
|
-
# expect(foo).to receive(:bar).at_least(:once)
|
22
|
-
# expect(foo).to receive(:bar).at_least(:twice)
|
23
|
-
# expect(foo).to receive(:bar).at_most(:once)
|
24
|
-
# expect(foo).to receive(:bar).at_most(:twice).times
|
17
|
+
# # good
|
18
|
+
# expect(foo).to receive(:bar).once
|
19
|
+
# expect(foo).to receive(:bar).twice
|
20
|
+
# expect(foo).to receive(:bar).at_least(:once)
|
21
|
+
# expect(foo).to receive(:bar).at_least(:twice)
|
22
|
+
# expect(foo).to receive(:bar).at_most(:once)
|
23
|
+
# expect(foo).to receive(:bar).at_most(:twice).times
|
25
24
|
#
|
26
25
|
class ReceiveCounts < Base
|
27
26
|
extend AutoCorrector
|
@@ -6,12 +6,11 @@ module RuboCop
|
|
6
6
|
# Prefer `not_to receive(...)` over `receive(...).never`.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
+
# # bad
|
10
|
+
# expect(foo).to receive(:bar).never
|
9
11
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# # good
|
14
|
-
# expect(foo).not_to receive(:bar)
|
12
|
+
# # good
|
13
|
+
# expect(foo).not_to receive(:bar)
|
15
14
|
#
|
16
15
|
class ReceiveNever < Base
|
17
16
|
extend AutoCorrector
|
@@ -6,44 +6,43 @@ module RuboCop
|
|
6
6
|
# Check for repeated description strings in example groups.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
+
# # bad
|
10
|
+
# RSpec.describe User do
|
11
|
+
# it 'is valid' do
|
12
|
+
# # ...
|
13
|
+
# end
|
9
14
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# it 'is valid' do
|
13
|
-
# # ...
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# it 'is valid' do
|
17
|
-
# # ...
|
18
|
-
# end
|
15
|
+
# it 'is valid' do
|
16
|
+
# # ...
|
19
17
|
# end
|
18
|
+
# end
|
20
19
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
20
|
+
# # good
|
21
|
+
# RSpec.describe User do
|
22
|
+
# it 'is valid when first and last name are present' do
|
23
|
+
# # ...
|
24
|
+
# end
|
26
25
|
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# end
|
26
|
+
# it 'is valid when last name only is present' do
|
27
|
+
# # ...
|
30
28
|
# end
|
29
|
+
# end
|
31
30
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
31
|
+
# # good
|
32
|
+
# RSpec.describe User do
|
33
|
+
# it 'is valid' do
|
34
|
+
# # ...
|
35
|
+
# end
|
37
36
|
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# end
|
37
|
+
# it 'is valid', :flag do
|
38
|
+
# # ...
|
41
39
|
# end
|
40
|
+
# end
|
42
41
|
#
|
43
42
|
class RepeatedDescription < Base
|
44
43
|
MSG = "Don't repeat descriptions within an example group."
|
45
44
|
|
46
|
-
def on_block(node)
|
45
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
47
46
|
return unless example_group?(node)
|
48
47
|
|
49
48
|
repeated_descriptions(node).each do |repeated_description|
|
@@ -18,7 +18,7 @@ module RuboCop
|
|
18
18
|
class RepeatedExample < Base
|
19
19
|
MSG = "Don't repeat examples within an example group."
|
20
20
|
|
21
|
-
def on_block(node)
|
21
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
22
22
|
return unless example_group?(node)
|
23
23
|
|
24
24
|
repeated_examples(node).each do |repeated_example|
|
@@ -6,42 +6,41 @@ module RuboCop
|
|
6
6
|
# Check for repeated describe and context block body.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
+
# # bad
|
10
|
+
# describe 'cool feature x' do
|
11
|
+
# it { cool_predicate }
|
12
|
+
# end
|
9
13
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# end
|
14
|
+
# describe 'cool feature y' do
|
15
|
+
# it { cool_predicate }
|
16
|
+
# end
|
14
17
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
+
# # good
|
19
|
+
# describe 'cool feature' do
|
20
|
+
# it { cool_predicate }
|
21
|
+
# end
|
18
22
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# end
|
23
|
+
# describe 'another cool feature' do
|
24
|
+
# it { another_predicate }
|
25
|
+
# end
|
23
26
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
+
# # good
|
28
|
+
# context 'when case x', :tag do
|
29
|
+
# it { cool_predicate }
|
30
|
+
# end
|
27
31
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# end
|
32
|
+
# context 'when case y' do
|
33
|
+
# it { cool_predicate }
|
34
|
+
# end
|
32
35
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
+
# # good
|
37
|
+
# context Array do
|
38
|
+
# it { is_expected.to respond_to :each }
|
39
|
+
# end
|
36
40
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# context Hash do
|
43
|
-
# it { is_expected.to respond_to :each }
|
44
|
-
# end
|
41
|
+
# context Hash do
|
42
|
+
# it { is_expected.to respond_to :each }
|
43
|
+
# end
|
45
44
|
#
|
46
45
|
class RepeatedExampleGroupBody < Base
|
47
46
|
MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
|
@@ -6,42 +6,41 @@ module RuboCop
|
|
6
6
|
# Check for repeated example group descriptions.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
+
# # bad
|
10
|
+
# describe 'cool feature' do
|
11
|
+
# # example group
|
12
|
+
# end
|
9
13
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# end
|
14
|
+
# describe 'cool feature' do
|
15
|
+
# # example group
|
16
|
+
# end
|
14
17
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
+
# # bad
|
19
|
+
# context 'when case x' do
|
20
|
+
# # example group
|
21
|
+
# end
|
18
22
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# end
|
23
|
+
# describe 'when case x' do
|
24
|
+
# # example group
|
25
|
+
# end
|
23
26
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
+
# # good
|
28
|
+
# describe 'cool feature' do
|
29
|
+
# # example group
|
30
|
+
# end
|
27
31
|
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# end
|
32
|
+
# describe 'another cool feature' do
|
33
|
+
# # example group
|
34
|
+
# end
|
32
35
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
+
# # good
|
37
|
+
# context 'when case x' do
|
38
|
+
# # example group
|
39
|
+
# end
|
36
40
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# context 'when another case' do
|
43
|
-
# # example group
|
44
|
-
# end
|
41
|
+
# context 'when another case' do
|
42
|
+
# # example group
|
43
|
+
# end
|
45
44
|
#
|
46
45
|
class RepeatedExampleGroupDescription < Base
|
47
46
|
MSG = 'Repeated %<group>s block description on line(s) %<loc>s'
|