rubocop-rspec 1.7.0 → 3.0.2
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 +5 -5
- data/CHANGELOG.md +955 -79
- data/CODE_OF_CONDUCT.md +17 -0
- data/MIT-LICENSE.md +1 -2
- data/README.md +35 -35
- data/config/default.yml +940 -52
- data/config/obsoletion.yml +30 -0
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +49 -0
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +49 -0
- data/lib/rubocop/cop/rspec/any_instance.rb +10 -13
- data/lib/rubocop/cop/rspec/around_block.rb +97 -0
- data/lib/rubocop/cop/rspec/base.rb +26 -0
- data/lib/rubocop/cop/rspec/be.rb +39 -0
- data/lib/rubocop/cop/rspec/be_empty.rb +45 -0
- data/lib/rubocop/cop/rspec/be_eq.rb +47 -0
- data/lib/rubocop/cop/rspec/be_eql.rb +18 -15
- data/lib/rubocop/cop/rspec/be_nil.rb +74 -0
- data/lib/rubocop/cop/rspec/before_after_all.rb +45 -0
- data/lib/rubocop/cop/rspec/change_by_zero.rb +184 -0
- data/lib/rubocop/cop/rspec/class_check.rb +101 -0
- data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
- data/lib/rubocop/cop/rspec/context_method.rb +57 -0
- data/lib/rubocop/cop/rspec/context_wording.rb +117 -0
- data/lib/rubocop/cop/rspec/describe_class.rb +52 -21
- data/lib/rubocop/cop/rspec/describe_method.rb +26 -11
- data/lib/rubocop/cop/rspec/describe_symbol.rb +37 -0
- data/lib/rubocop/cop/rspec/described_class.rb +181 -34
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +38 -0
- data/lib/rubocop/cop/rspec/dialect.rb +84 -0
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +58 -0
- data/lib/rubocop/cop/rspec/empty_example_group.rb +134 -47
- data/lib/rubocop/cop/rspec/empty_hook.rb +49 -0
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +82 -0
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +42 -0
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +40 -0
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +82 -0
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +36 -0
- data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
- data/lib/rubocop/cop/rspec/empty_output.rb +47 -0
- data/lib/rubocop/cop/rspec/eq.rb +47 -0
- data/lib/rubocop/cop/rspec/example_length.rb +38 -20
- data/lib/rubocop/cop/rspec/example_without_description.rb +98 -0
- data/lib/rubocop/cop/rspec/example_wording.rb +117 -27
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +110 -0
- data/lib/rubocop/cop/rspec/expect_actual.rb +46 -20
- data/lib/rubocop/cop/rspec/expect_change.rb +86 -0
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +50 -0
- data/lib/rubocop/cop/rspec/expect_in_let.rb +42 -0
- data/lib/rubocop/cop/rspec/expect_output.rb +50 -0
- data/lib/rubocop/cop/rspec/focus.rb +79 -25
- data/lib/rubocop/cop/rspec/hook_argument.rb +48 -36
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +81 -0
- data/lib/rubocop/cop/rspec/identical_equality_assertion.rb +37 -0
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +68 -0
- data/lib/rubocop/cop/rspec/implicit_expect.rb +100 -0
- data/lib/rubocop/cop/rspec/implicit_subject.rb +167 -0
- data/lib/rubocop/cop/rspec/indexed_let.rb +112 -0
- data/lib/rubocop/cop/rspec/instance_spy.rb +74 -0
- data/lib/rubocop/cop/rspec/instance_variable.rb +28 -14
- data/lib/rubocop/cop/rspec/is_expected_specify.rb +45 -0
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +49 -0
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +74 -0
- data/lib/rubocop/cop/rspec/leading_subject.rb +57 -29
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +127 -0
- data/lib/rubocop/cop/rspec/let_before_examples.rb +101 -0
- data/lib/rubocop/cop/rspec/let_setup.rb +32 -16
- data/lib/rubocop/cop/rspec/match_array.rb +59 -0
- data/lib/rubocop/cop/rspec/message_chain.rb +10 -15
- data/lib/rubocop/cop/rspec/message_expectation.rb +12 -9
- data/lib/rubocop/cop/rspec/message_spies.rb +88 -0
- data/lib/rubocop/cop/rspec/metadata_style.rb +202 -0
- data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +35 -0
- data/lib/rubocop/cop/rspec/missing_expectation_target_method.rb +54 -0
- data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
- data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +59 -0
- data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
- data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
- data/lib/rubocop/cop/rspec/mixin/inside_example_group.rb +29 -0
- data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +63 -0
- data/lib/rubocop/cop/rspec/mixin/namespace.rb +23 -0
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +39 -0
- data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
- data/lib/rubocop/cop/rspec/mixin/variable.rb +21 -0
- data/lib/rubocop/cop/rspec/multiple_describes.rb +14 -12
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +86 -26
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +146 -0
- data/lib/rubocop/cop/rspec/multiple_subjects.rb +97 -0
- data/lib/rubocop/cop/rspec/named_subject.rb +107 -27
- data/lib/rubocop/cop/rspec/nested_groups.rb +84 -47
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +102 -0
- data/lib/rubocop/cop/rspec/not_to_not.rb +30 -27
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +74 -0
- data/lib/rubocop/cop/rspec/pending.rb +80 -0
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +159 -0
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +341 -0
- data/lib/rubocop/cop/rspec/receive_counts.rb +89 -0
- data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
- data/lib/rubocop/cop/rspec/receive_never.rb +41 -0
- data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
- data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +67 -0
- data/lib/rubocop/cop/rspec/remove_const.rb +39 -0
- data/lib/rubocop/cop/rspec/repeated_description.rb +98 -0
- data/lib/rubocop/cop/rspec/repeated_example.rb +53 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +100 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +96 -0
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +105 -0
- data/lib/rubocop/cop/rspec/repeated_subject_call.rb +125 -0
- data/lib/rubocop/cop/rspec/return_from_stub.rb +169 -0
- data/lib/rubocop/cop/rspec/scattered_let.rb +59 -0
- data/lib/rubocop/cop/rspec/scattered_setup.rb +92 -0
- data/lib/rubocop/cop/rspec/shared_context.rb +107 -0
- data/lib/rubocop/cop/rspec/shared_examples.rb +125 -0
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +93 -0
- data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
- data/lib/rubocop/cop/rspec/sort_metadata.rb +71 -0
- data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
- data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +176 -0
- data/lib/rubocop/cop/rspec/subject_declaration.rb +46 -0
- data/lib/rubocop/cop/rspec/subject_stub.rb +93 -74
- data/lib/rubocop/cop/rspec/undescriptive_literals_description.rb +69 -0
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +67 -0
- data/lib/rubocop/cop/rspec/variable_definition.rb +77 -0
- data/lib/rubocop/cop/rspec/variable_name.rb +68 -0
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +111 -0
- data/lib/rubocop/cop/rspec/verified_doubles.rb +28 -14
- data/lib/rubocop/cop/rspec/void_expect.rb +60 -0
- data/lib/rubocop/cop/rspec/yield.rb +82 -0
- data/lib/rubocop/cop/rspec_cops.rb +112 -0
- data/lib/rubocop/rspec/align_let_brace.rb +63 -0
- data/lib/rubocop/rspec/concept.rb +33 -0
- data/lib/rubocop/rspec/config_formatter.rb +27 -4
- data/lib/rubocop/rspec/cop/generator.rb +25 -0
- data/lib/rubocop/rspec/corrector/move_node.rb +51 -0
- data/lib/rubocop/rspec/description_extractor.rb +60 -18
- data/lib/rubocop/rspec/example.rb +37 -0
- data/lib/rubocop/rspec/example_group.rb +67 -0
- data/lib/rubocop/rspec/hook.rb +79 -0
- data/lib/rubocop/rspec/inject.rb +3 -1
- data/lib/rubocop/rspec/language.rb +184 -41
- data/lib/rubocop/rspec/node.rb +19 -0
- data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +29 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop/rspec/wording.rb +61 -19
- data/lib/rubocop/rspec.rb +6 -2
- data/lib/rubocop-rspec.rb +45 -34
- metadata +130 -195
- data/Gemfile +0 -13
- data/Rakefile +0 -48
- data/lib/rubocop/cop/rspec/file_path.rb +0 -83
- data/lib/rubocop/rspec/language/node_pattern.rb +0 -16
- data/lib/rubocop/rspec/spec_only.rb +0 -61
- data/lib/rubocop/rspec/top_level_describe.rb +0 -61
- data/lib/rubocop/rspec/util.rb +0 -19
- data/rubocop-rspec.gemspec +0 -42
- data/spec/expect_violation/expectation_spec.rb +0 -85
- data/spec/project/changelog_spec.rb +0 -81
- data/spec/project/default_config_spec.rb +0 -52
- data/spec/project/project_requires_spec.rb +0 -8
- data/spec/rubocop/cop/rspec/any_instance_spec.rb +0 -30
- data/spec/rubocop/cop/rspec/be_eql_spec.rb +0 -59
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +0 -113
- data/spec/rubocop/cop/rspec/describe_method_spec.rb +0 -32
- data/spec/rubocop/cop/rspec/described_class_spec.rb +0 -219
- data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +0 -79
- data/spec/rubocop/cop/rspec/example_length_spec.rb +0 -117
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +0 -82
- data/spec/rubocop/cop/rspec/expect_actual_spec.rb +0 -136
- data/spec/rubocop/cop/rspec/file_path_spec.rb +0 -236
- data/spec/rubocop/cop/rspec/focus_spec.rb +0 -130
- data/spec/rubocop/cop/rspec/hook_argument_spec.rb +0 -189
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +0 -75
- data/spec/rubocop/cop/rspec/leading_subject_spec.rb +0 -54
- data/spec/rubocop/cop/rspec/let_setup_spec.rb +0 -66
- data/spec/rubocop/cop/rspec/message_chain_spec.rb +0 -21
- data/spec/rubocop/cop/rspec/message_expectation_spec.rb +0 -63
- data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +0 -28
- data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +0 -84
- data/spec/rubocop/cop/rspec/named_subject_spec.rb +0 -62
- data/spec/rubocop/cop/rspec/nested_groups_spec.rb +0 -55
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +0 -57
- data/spec/rubocop/cop/rspec/subject_stub_spec.rb +0 -183
- data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +0 -71
- data/spec/rubocop/rspec/config_formatter_spec.rb +0 -48
- data/spec/rubocop/rspec/description_extractor_spec.rb +0 -35
- data/spec/rubocop/rspec/language/selector_set_spec.rb +0 -29
- data/spec/rubocop/rspec/spec_only_spec.rb +0 -97
- data/spec/rubocop/rspec/util/one_spec.rb +0 -21
- data/spec/rubocop/rspec/wording_spec.rb +0 -44
- data/spec/shared/rspec_only_cop_behavior.rb +0 -68
- data/spec/spec_helper.rb +0 -41
- data/spec/support/expect_violation.rb +0 -166
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for empty before and after hooks.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# before {}
|
11
|
+
# after do; end
|
12
|
+
# before(:all) do
|
13
|
+
# end
|
14
|
+
# after(:all) { }
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# before { create_users }
|
18
|
+
# after do
|
19
|
+
# cleanup_users
|
20
|
+
# end
|
21
|
+
# before(:all) do
|
22
|
+
# create_feed
|
23
|
+
# end
|
24
|
+
# after(:all) { cleanup_feed }
|
25
|
+
#
|
26
|
+
class EmptyHook < Base
|
27
|
+
extend AutoCorrector
|
28
|
+
include RuboCop::Cop::RangeHelp
|
29
|
+
|
30
|
+
MSG = 'Empty hook detected.'
|
31
|
+
|
32
|
+
# @!method empty_hook?(node)
|
33
|
+
def_node_matcher :empty_hook?, <<~PATTERN
|
34
|
+
(block $(send nil? #Hooks.all ...) _ nil?)
|
35
|
+
PATTERN
|
36
|
+
|
37
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
38
|
+
empty_hook?(node) do |hook|
|
39
|
+
add_offense(hook) do |corrector|
|
40
|
+
corrector.remove(
|
41
|
+
range_with_surrounding_space(node.source_range, side: :left)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is an empty line after example blocks.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# RSpec.describe Foo do
|
11
|
+
# it 'does this' do
|
12
|
+
# end
|
13
|
+
# it 'does that' do
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# RSpec.describe Foo do
|
19
|
+
# it 'does this' do
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# it 'does that' do
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # fair - it's ok to have non-separated one-liners
|
27
|
+
# RSpec.describe Foo do
|
28
|
+
# it { one }
|
29
|
+
# it { two }
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# @example with AllowConsecutiveOneLiners configuration
|
33
|
+
# # rubocop.yml
|
34
|
+
# # RSpec/EmptyLineAfterExample:
|
35
|
+
# # AllowConsecutiveOneLiners: false
|
36
|
+
#
|
37
|
+
# # bad
|
38
|
+
# RSpec.describe Foo do
|
39
|
+
# it { one }
|
40
|
+
# it { two }
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
class EmptyLineAfterExample < Base
|
44
|
+
extend AutoCorrector
|
45
|
+
include EmptyLineSeparation
|
46
|
+
|
47
|
+
MSG = 'Add an empty line after `%<example>s`.'
|
48
|
+
|
49
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
50
|
+
return unless example?(node)
|
51
|
+
return if allowed_one_liner?(node)
|
52
|
+
|
53
|
+
missing_separating_line_offense(node) do |method|
|
54
|
+
format(MSG, example: method)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def allowed_one_liner?(node)
|
61
|
+
consecutive_one_liner?(node) && allow_consecutive_one_liners?
|
62
|
+
end
|
63
|
+
|
64
|
+
def allow_consecutive_one_liners?
|
65
|
+
cop_config['AllowConsecutiveOneLiners']
|
66
|
+
end
|
67
|
+
|
68
|
+
def consecutive_one_liner?(node)
|
69
|
+
node.single_line? && next_one_line_example?(node)
|
70
|
+
end
|
71
|
+
|
72
|
+
def next_one_line_example?(node)
|
73
|
+
next_sibling = node.right_sibling
|
74
|
+
return false unless next_sibling
|
75
|
+
return false unless example?(next_sibling)
|
76
|
+
|
77
|
+
next_sibling.single_line?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is an empty line after example group blocks.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# RSpec.describe Foo do
|
11
|
+
# describe '#bar' do
|
12
|
+
# end
|
13
|
+
# describe '#baz' do
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# RSpec.describe Foo do
|
19
|
+
# describe '#bar' do
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# describe '#baz' do
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
class EmptyLineAfterExampleGroup < Base
|
27
|
+
extend AutoCorrector
|
28
|
+
include EmptyLineSeparation
|
29
|
+
|
30
|
+
MSG = 'Add an empty line after `%<example_group>s`.'
|
31
|
+
|
32
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
33
|
+
return unless spec_group?(node)
|
34
|
+
|
35
|
+
missing_separating_line_offense(node) do |method|
|
36
|
+
format(MSG, example_group: method)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is an empty line after the last let block.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# let(:foo) { bar }
|
11
|
+
# let(:something) { other }
|
12
|
+
# it { does_something }
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# let(:foo) { bar }
|
16
|
+
# let(:something) { other }
|
17
|
+
#
|
18
|
+
# it { does_something }
|
19
|
+
#
|
20
|
+
class EmptyLineAfterFinalLet < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
include EmptyLineSeparation
|
23
|
+
|
24
|
+
MSG = 'Add an empty line after the last `%<let>s`.'
|
25
|
+
|
26
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
27
|
+
return unless example_group_with_body?(node)
|
28
|
+
|
29
|
+
final_let = node.body.child_nodes.reverse.find { |child| let?(child) }
|
30
|
+
|
31
|
+
return if final_let.nil?
|
32
|
+
|
33
|
+
missing_separating_line_offense(final_let) do |method|
|
34
|
+
format(MSG, let: method)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is an empty line after hook blocks.
|
7
|
+
#
|
8
|
+
# `AllowConsecutiveOneLiners` configures whether adjacent
|
9
|
+
# one-line definitions are considered an offense.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# before { do_something }
|
14
|
+
# it { does_something }
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# after { do_something }
|
18
|
+
# it { does_something }
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# around { |test| test.run }
|
22
|
+
# it { does_something }
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# after { do_something }
|
26
|
+
#
|
27
|
+
# it { does_something }
|
28
|
+
#
|
29
|
+
# # fair - it's ok to have non-separated one-liners hooks
|
30
|
+
# around { |test| test.run }
|
31
|
+
# after { do_something }
|
32
|
+
#
|
33
|
+
# it { does_something }
|
34
|
+
#
|
35
|
+
# @example with AllowConsecutiveOneLiners configuration
|
36
|
+
# # rubocop.yml
|
37
|
+
# # RSpec/EmptyLineAfterHook:
|
38
|
+
# # AllowConsecutiveOneLiners: false
|
39
|
+
#
|
40
|
+
# # bad
|
41
|
+
# around { |test| test.run }
|
42
|
+
# after { do_something }
|
43
|
+
#
|
44
|
+
# it { does_something }
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# around { |test| test.run }
|
48
|
+
#
|
49
|
+
# after { do_something }
|
50
|
+
#
|
51
|
+
# it { does_something }
|
52
|
+
#
|
53
|
+
class EmptyLineAfterHook < Base
|
54
|
+
extend AutoCorrector
|
55
|
+
include ConfigurableEnforcedStyle
|
56
|
+
include EmptyLineSeparation
|
57
|
+
|
58
|
+
MSG = 'Add an empty line after `%<hook>s`.'
|
59
|
+
|
60
|
+
def on_block(node)
|
61
|
+
return unless hook?(node)
|
62
|
+
return if cop_config['AllowConsecutiveOneLiners'] &&
|
63
|
+
chained_single_line_hooks?(node)
|
64
|
+
|
65
|
+
missing_separating_line_offense(node) do |method|
|
66
|
+
format(MSG, hook: method)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
alias on_numblock on_block
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def chained_single_line_hooks?(node)
|
75
|
+
next_node = node.right_sibling
|
76
|
+
|
77
|
+
hook?(next_node) && node.single_line? && next_node.single_line?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is an empty line after subject block.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# subject(:obj) { described_class }
|
11
|
+
# let(:foo) { bar }
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# subject(:obj) { described_class }
|
15
|
+
#
|
16
|
+
# let(:foo) { bar }
|
17
|
+
#
|
18
|
+
class EmptyLineAfterSubject < Base
|
19
|
+
extend AutoCorrector
|
20
|
+
include EmptyLineSeparation
|
21
|
+
include InsideExampleGroup
|
22
|
+
|
23
|
+
MSG = 'Add an empty line after `%<subject>s`.'
|
24
|
+
|
25
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
26
|
+
return unless subject?(node)
|
27
|
+
return unless inside_example_group?(node)
|
28
|
+
|
29
|
+
missing_separating_line_offense(node) do |method|
|
30
|
+
format(MSG, subject: method)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Avoid empty metadata hash.
|
7
|
+
#
|
8
|
+
# @example EnforcedStyle: symbol (default)
|
9
|
+
# # bad
|
10
|
+
# describe 'Something', {}
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# describe 'Something'
|
14
|
+
class EmptyMetadata < Base
|
15
|
+
extend AutoCorrector
|
16
|
+
|
17
|
+
include Metadata
|
18
|
+
include RangeHelp
|
19
|
+
|
20
|
+
MSG = 'Avoid empty metadata hash.'
|
21
|
+
|
22
|
+
def on_metadata(_symbols, hash)
|
23
|
+
return unless hash&.pairs&.empty?
|
24
|
+
|
25
|
+
add_offense(hash) do |corrector|
|
26
|
+
remove_empty_metadata(corrector, hash)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def remove_empty_metadata(corrector, node)
|
33
|
+
corrector.remove(
|
34
|
+
range_with_surrounding_comma(
|
35
|
+
range_with_surrounding_space(
|
36
|
+
node.source_range,
|
37
|
+
side: :left
|
38
|
+
),
|
39
|
+
:left
|
40
|
+
)
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Check that the `output` matcher is not called with an empty string.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# expect { foo }.to output('').to_stdout
|
11
|
+
# expect { bar }.not_to output('').to_stderr
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# expect { foo }.not_to output.to_stdout
|
15
|
+
# expect { bar }.to output.to_stderr
|
16
|
+
#
|
17
|
+
class EmptyOutput < Base
|
18
|
+
extend AutoCorrector
|
19
|
+
|
20
|
+
MSG = 'Use `%<runner>s` instead of matching on an empty output.'
|
21
|
+
RESTRICT_ON_SEND = Runners.all
|
22
|
+
|
23
|
+
# @!method matching_empty_output(node)
|
24
|
+
def_node_matcher :matching_empty_output, <<~PATTERN
|
25
|
+
(send
|
26
|
+
(block
|
27
|
+
(send nil? :expect) ...
|
28
|
+
)
|
29
|
+
#Runners.all
|
30
|
+
(send $(send nil? :output (str empty?)) ...)
|
31
|
+
)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_send(send_node)
|
35
|
+
matching_empty_output(send_node) do |node|
|
36
|
+
runner = send_node.method?(:to) ? 'not_to' : 'to'
|
37
|
+
message = format(MSG, runner: runner)
|
38
|
+
add_offense(node, message: message) do |corrector|
|
39
|
+
corrector.replace(send_node.loc.selector, runner)
|
40
|
+
corrector.replace(node, 'output')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Use `eq` instead of `be ==` to compare objects.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# expect(foo).to be == 42
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# expect(foo).to eq 42
|
14
|
+
#
|
15
|
+
class Eq < Base
|
16
|
+
extend AutoCorrector
|
17
|
+
include RangeHelp
|
18
|
+
|
19
|
+
MSG = 'Use `eq` instead of `be ==` to compare objects.'
|
20
|
+
RESTRICT_ON_SEND = Runners.all
|
21
|
+
|
22
|
+
# @!method be_equals(node)
|
23
|
+
def_node_matcher :be_equals, <<~PATTERN
|
24
|
+
(send _ #Runners.all $(send (send nil? :be) :== _))
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
def on_send(node)
|
28
|
+
be_equals(node) do |matcher|
|
29
|
+
range = offense_range(matcher)
|
30
|
+
add_offense(range) do |corrector|
|
31
|
+
corrector.replace(range, 'eq')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def offense_range(matcher)
|
39
|
+
range_between(
|
40
|
+
matcher.source_range.begin_pos,
|
41
|
+
matcher.loc.selector.end_pos
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
# Checks for long examples.
|
7
7
|
#
|
8
8
|
# A long example is usually more difficult to understand. Consider
|
9
|
-
# extracting out some
|
9
|
+
# extracting out some behavior, e.g. with a `let` block, or a helper
|
10
10
|
# method.
|
11
11
|
#
|
12
12
|
# @example
|
@@ -25,32 +25,50 @@ module RuboCop
|
|
25
25
|
# result = service.call
|
26
26
|
# expect(result).to be(true)
|
27
27
|
# end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
#
|
29
|
+
# You can set constructs you want to fold with `CountAsOne`.
|
30
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'.
|
31
|
+
# Each construct will be counted as one line regardless of
|
32
|
+
# its actual size.
|
33
|
+
#
|
34
|
+
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
35
|
+
#
|
36
|
+
# it do
|
37
|
+
# array = [ # +1
|
38
|
+
# 1,
|
39
|
+
# 2
|
40
|
+
# ]
|
41
|
+
#
|
42
|
+
# hash = { # +3
|
43
|
+
# key: 'value'
|
44
|
+
# }
|
45
|
+
#
|
46
|
+
# msg = <<~HEREDOC # +1
|
47
|
+
# Heredoc
|
48
|
+
# content.
|
49
|
+
# HEREDOC
|
50
|
+
#
|
51
|
+
# foo( # +1
|
52
|
+
# 1,
|
53
|
+
# 2
|
54
|
+
# )
|
55
|
+
# end # 6 points
|
56
|
+
#
|
57
|
+
class ExampleLength < Base
|
58
|
+
include CodeLength
|
32
59
|
|
33
|
-
|
34
|
-
method, _args, _body = *node
|
35
|
-
_receiver, method_name, _object = *method
|
36
|
-
return unless EXAMPLE_BLOCKS.include?(method_name)
|
60
|
+
LABEL = 'Example'
|
37
61
|
|
38
|
-
|
62
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
63
|
+
return unless example?(node)
|
39
64
|
|
40
|
-
|
41
|
-
add_offense(node, :expression, message(length))
|
65
|
+
check_code_length(node)
|
42
66
|
end
|
43
67
|
|
44
68
|
private
|
45
69
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
lines.count { |line| !irrelevant_line(line) }
|
50
|
-
end
|
51
|
-
|
52
|
-
def message(length)
|
53
|
-
format('Example has too many lines. [%d/%d]', length, max_length)
|
70
|
+
def cop_label
|
71
|
+
LABEL
|
54
72
|
end
|
55
73
|
end
|
56
74
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for examples without a description.
|
7
|
+
#
|
8
|
+
# RSpec allows for auto-generated example descriptions when there is no
|
9
|
+
# description provided or the description is an empty one.
|
10
|
+
# It is acceptable to use `specify` without a description
|
11
|
+
#
|
12
|
+
# This cop removes empty descriptions.
|
13
|
+
# It also defines whether auto-generated description is allowed, based
|
14
|
+
# on the configured style.
|
15
|
+
#
|
16
|
+
# This cop can be configured using the `EnforcedStyle` option
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# # always good
|
20
|
+
# specify do
|
21
|
+
# result = service.call
|
22
|
+
# expect(result).to be(true)
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @example `EnforcedStyle: always_allow` (default)
|
26
|
+
# # bad
|
27
|
+
# it('') { is_expected.to be_good }
|
28
|
+
# specify '' do
|
29
|
+
# result = service.call
|
30
|
+
# expect(result).to be(true)
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# it { is_expected.to be_good }
|
35
|
+
# specify do
|
36
|
+
# result = service.call
|
37
|
+
# expect(result).to be(true)
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# @example `EnforcedStyle: single_line_only`
|
41
|
+
# # bad
|
42
|
+
# it('') { is_expected.to be_good }
|
43
|
+
# it do
|
44
|
+
# result = service.call
|
45
|
+
# expect(result).to be(true)
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# # good
|
49
|
+
# it { is_expected.to be_good }
|
50
|
+
#
|
51
|
+
# @example `EnforcedStyle: disallow`
|
52
|
+
# # bad
|
53
|
+
# it { is_expected.to be_good }
|
54
|
+
# it do
|
55
|
+
# result = service.call
|
56
|
+
# expect(result).to be(true)
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
class ExampleWithoutDescription < Base
|
60
|
+
include ConfigurableEnforcedStyle
|
61
|
+
|
62
|
+
MSG_DEFAULT_ARGUMENT = 'Omit the argument when you want to ' \
|
63
|
+
'have auto-generated description.'
|
64
|
+
MSG_ADD_DESCRIPTION = 'Add a description.'
|
65
|
+
|
66
|
+
# @!method example_description(node)
|
67
|
+
def_node_matcher :example_description, '(send nil? _ $(str $_))'
|
68
|
+
|
69
|
+
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
70
|
+
return unless example?(node)
|
71
|
+
|
72
|
+
check_example_without_description(node.send_node)
|
73
|
+
|
74
|
+
example_description(node.send_node) do |message_node, message|
|
75
|
+
return unless message.to_s.empty?
|
76
|
+
|
77
|
+
add_offense(message_node, message: MSG_DEFAULT_ARGUMENT)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def check_example_without_description(node)
|
84
|
+
return if node.arguments?
|
85
|
+
return unless disallow_empty_description?(node)
|
86
|
+
return if node.method?(:specify) && node.parent.multiline?
|
87
|
+
|
88
|
+
add_offense(node, message: MSG_ADD_DESCRIPTION)
|
89
|
+
end
|
90
|
+
|
91
|
+
def disallow_empty_description?(node)
|
92
|
+
style == :disallow ||
|
93
|
+
(style == :single_line_only && node.parent.multiline?)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|