rubocop-rspec 2.16.0 → 2.24.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 +124 -9
- data/README.md +3 -3
- data/config/default.yml +145 -18
- data/config/obsoletion.yml +15 -0
- data/lib/rubocop/cop/rspec/be_empty.rb +44 -0
- data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +29 -115
- data/lib/rubocop/cop/rspec/capybara/match_style.rb +38 -0
- data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +23 -96
- data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +19 -75
- data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +14 -83
- data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +25 -69
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +26 -63
- data/lib/rubocop/cop/rspec/change_by_zero.rb +33 -23
- data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
- data/lib/rubocop/cop/rspec/context_method.rb +5 -1
- data/lib/rubocop/cop/rspec/context_wording.rb +13 -6
- data/lib/rubocop/cop/rspec/describe_method.rb +16 -8
- data/lib/rubocop/cop/rspec/described_class.rb +2 -1
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +7 -5
- data/lib/rubocop/cop/rspec/dialect.rb +1 -1
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +2 -2
- data/lib/rubocop/cop/rspec/empty_example_group.rb +10 -7
- data/lib/rubocop/cop/rspec/empty_hook.rb +2 -2
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
- data/lib/rubocop/cop/rspec/eq.rb +47 -0
- data/lib/rubocop/cop/rspec/example_wording.rb +1 -1
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +14 -5
- data/lib/rubocop/cop/rspec/expect_actual.rb +4 -4
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +25 -118
- data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +40 -107
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +30 -250
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +19 -46
- data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +23 -64
- data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +45 -79
- data/lib/rubocop/cop/rspec/file_path.rb +8 -2
- data/lib/rubocop/cop/rspec/focus.rb +19 -5
- data/lib/rubocop/cop/rspec/hook_argument.rb +12 -9
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +5 -3
- data/lib/rubocop/cop/rspec/indexed_let.rb +112 -0
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +8 -4
- data/lib/rubocop/cop/rspec/let_setup.rb +6 -8
- data/lib/rubocop/cop/rspec/match_array.rb +59 -0
- data/lib/rubocop/cop/rspec/metadata_style.rb +197 -0
- data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +1 -2
- data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
- data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +21 -7
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +20 -4
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +2 -1
- data/lib/rubocop/cop/rspec/named_subject.rb +7 -5
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +2 -5
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +3 -1
- data/lib/rubocop/cop/rspec/pending.rb +23 -13
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +72 -36
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +49 -40
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +11 -6
- data/lib/rubocop/cop/rspec/rails/http_status.rb +107 -34
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +4 -4
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +60 -0
- data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +102 -0
- data/lib/rubocop/cop/rspec/rails/travel_around.rb +92 -0
- data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
- data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +3 -6
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +3 -6
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -4
- data/lib/rubocop/cop/rspec/scattered_setup.rb +23 -6
- data/lib/rubocop/cop/rspec/shared_context.rb +12 -13
- data/lib/rubocop/cop/rspec/shared_examples.rb +6 -4
- data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
- data/lib/rubocop/cop/rspec/sort_metadata.rb +4 -3
- 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 +1 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +0 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +5 -2
- data/lib/rubocop/cop/rspec/variable_name.rb +4 -1
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +7 -7
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
- data/lib/rubocop/cop/rspec/void_expect.rb +2 -1
- data/lib/rubocop/cop/rspec_cops.rb +16 -0
- data/lib/rubocop/rspec/config_formatter.rb +16 -0
- data/lib/rubocop/rspec/example_group.rb +6 -8
- data/lib/rubocop/rspec/language/node_pattern.rb +26 -0
- data/lib/rubocop/rspec/language.rb +25 -16
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +4 -5
- metadata +50 -8
- data/lib/rubocop/cop/rspec/mixin/capybara_help.rb +0 -80
- data/lib/rubocop/cop/rspec/mixin/css_selector.rb +0 -146
- data/lib/rubocop/rspec/factory_bot/language.rb +0 -37
- data/lib/rubocop/rspec/factory_bot.rb +0 -64
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that spec file paths are consistent and well-formed.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# whatever_spec.rb # describe MyClass
|
11
|
+
# my_class_spec.rb # describe MyClass, '#method'
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# my_class_spec.rb # describe MyClass
|
15
|
+
# my_class_method_spec.rb # describe MyClass, '#method'
|
16
|
+
# my_class/method_spec.rb # describe MyClass, '#method'
|
17
|
+
#
|
18
|
+
# @example `CustomTransform: {RuboCop=>rubocop, RSpec=>rspec}` (default)
|
19
|
+
# # good
|
20
|
+
# rubocop_spec.rb # describe RuboCop
|
21
|
+
# rspec_spec.rb # describe RSpec
|
22
|
+
#
|
23
|
+
# @example `IgnoreMethods: false` (default)
|
24
|
+
# # bad
|
25
|
+
# my_class_spec.rb # describe MyClass, '#method'
|
26
|
+
#
|
27
|
+
# @example `IgnoreMethods: true`
|
28
|
+
# # good
|
29
|
+
# my_class_spec.rb # describe MyClass, '#method'
|
30
|
+
#
|
31
|
+
# @example `IgnoreMetadata: {type=>routing}` (default)
|
32
|
+
# # good
|
33
|
+
# whatever_spec.rb # describe MyClass, type: :routing do; end
|
34
|
+
#
|
35
|
+
class SpecFilePathFormat < Base
|
36
|
+
include TopLevelGroup
|
37
|
+
include Namespace
|
38
|
+
include FileHelp
|
39
|
+
|
40
|
+
MSG = 'Spec path should end with `%<suffix>s`.'
|
41
|
+
|
42
|
+
# @!method example_group_arguments(node)
|
43
|
+
def_node_matcher :example_group_arguments, <<~PATTERN
|
44
|
+
(block (send #rspec? #ExampleGroups.all $_ $...) ...)
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
# @!method metadata_key_value(node)
|
48
|
+
def_node_search :metadata_key_value, '(pair (sym $_key) (sym $_value))'
|
49
|
+
|
50
|
+
def on_top_level_example_group(node)
|
51
|
+
return unless top_level_groups.one?
|
52
|
+
|
53
|
+
example_group_arguments(node) do |class_name, arguments|
|
54
|
+
next if !class_name.const_type? || ignore_metadata?(arguments)
|
55
|
+
|
56
|
+
ensure_correct_file_path(class_name, arguments)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def ensure_correct_file_path(class_name, arguments)
|
63
|
+
pattern = correct_path_pattern(class_name, arguments)
|
64
|
+
return if filename_ends_with?(pattern)
|
65
|
+
|
66
|
+
# For the suffix shown in the offense message, modify the regular
|
67
|
+
# expression pattern to resemble a glob pattern for clearer error
|
68
|
+
# messages.
|
69
|
+
suffix = pattern.sub('.*', '*').sub('[^/]*', '*').sub('\.', '.')
|
70
|
+
add_global_offense(format(MSG, suffix: suffix))
|
71
|
+
end
|
72
|
+
|
73
|
+
def ignore_metadata?(arguments)
|
74
|
+
arguments.any? do |argument|
|
75
|
+
metadata_key_value(argument).any? do |key, value|
|
76
|
+
ignore_metadata.values_at(key.to_s).include?(value.to_s)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def correct_path_pattern(class_name, arguments)
|
82
|
+
path = [expected_path(class_name)]
|
83
|
+
path << '.*' unless ignore?(arguments.first)
|
84
|
+
path << [name_pattern(arguments.first), '[^/]*_spec\.rb']
|
85
|
+
path.join
|
86
|
+
end
|
87
|
+
|
88
|
+
def name_pattern(method_name)
|
89
|
+
return if ignore?(method_name)
|
90
|
+
|
91
|
+
method_name.str_content.gsub(/\s/, '_').gsub(/\W/, '')
|
92
|
+
end
|
93
|
+
|
94
|
+
def ignore?(method_name)
|
95
|
+
!method_name&.str_type? || ignore_methods?
|
96
|
+
end
|
97
|
+
|
98
|
+
def expected_path(constant)
|
99
|
+
constants = namespace(constant) + constant.const_name.split('::')
|
100
|
+
|
101
|
+
File.join(
|
102
|
+
constants.map do |name|
|
103
|
+
custom_transform.fetch(name) { camel_to_snake_case(name) }
|
104
|
+
end
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def camel_to_snake_case(string)
|
109
|
+
string
|
110
|
+
.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
|
111
|
+
.gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
|
112
|
+
.downcase
|
113
|
+
end
|
114
|
+
|
115
|
+
def custom_transform
|
116
|
+
cop_config.fetch('CustomTransform', {})
|
117
|
+
end
|
118
|
+
|
119
|
+
def ignore_methods?
|
120
|
+
cop_config['IgnoreMethods']
|
121
|
+
end
|
122
|
+
|
123
|
+
def ignore_metadata
|
124
|
+
cop_config.fetch('IgnoreMetadata', {})
|
125
|
+
end
|
126
|
+
|
127
|
+
def filename_ends_with?(pattern)
|
128
|
+
expanded_file_path.match?("#{pattern}$")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that spec file paths suffix are consistent and well-formed.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# my_class/foo_specorb.rb # describe MyClass
|
11
|
+
# spec/models/user.rb # describe User
|
12
|
+
# spec/models/user_specxrb # describe User
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# my_class_spec.rb # describe MyClass
|
16
|
+
#
|
17
|
+
# # good - shared examples are allowed
|
18
|
+
# spec/models/user.rb # shared_examples_for 'foo'
|
19
|
+
#
|
20
|
+
class SpecFilePathSuffix < Base
|
21
|
+
include TopLevelGroup
|
22
|
+
include FileHelp
|
23
|
+
|
24
|
+
MSG = 'Spec path should end with `_spec.rb`.'
|
25
|
+
|
26
|
+
def on_top_level_example_group(node)
|
27
|
+
example_group?(node) do
|
28
|
+
add_global_offense(MSG) unless correct_path?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def correct_path?
|
35
|
+
expanded_file_path.end_with?('_spec.rb')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -91,7 +91,7 @@ module RuboCop
|
|
91
91
|
# @param node [RuboCop::AST::Node]
|
92
92
|
# @yield [RuboCop::AST::Node] matcher
|
93
93
|
def_node_matcher :matcher_with_return_block, <<~PATTERN
|
94
|
-
(block #message_expectation? args _) # receive(:foo) { 'bar' }
|
94
|
+
(block #message_expectation? (args) _) # receive(:foo) { 'bar' }
|
95
95
|
PATTERN
|
96
96
|
|
97
97
|
# @!method matcher_with_hash(node)
|
@@ -12,7 +12,6 @@ module RuboCop
|
|
12
12
|
#
|
13
13
|
# @see https://robots.thoughtbot.com/don-t-stub-the-system-under-test
|
14
14
|
# @see https://penelope.zone/2015/12/27/introducing-rspec-smells-and-where-to-find-them.html#smell-1-stubjec
|
15
|
-
# @see https://github.com/rubocop-hq/rspec-style-guide#dont-stub-subject
|
16
15
|
#
|
17
16
|
# @example
|
18
17
|
# # bad
|
@@ -27,12 +27,15 @@ module RuboCop
|
|
27
27
|
extend AutoCorrector
|
28
28
|
include ConfigurableEnforcedStyle
|
29
29
|
include Variable
|
30
|
+
include InsideExampleGroup
|
30
31
|
|
31
32
|
MSG = 'Use %<style>s for variable names.'
|
32
33
|
|
33
34
|
def on_send(node)
|
35
|
+
return unless inside_example_group?(node)
|
36
|
+
|
34
37
|
variable_definition?(node) do |variable|
|
35
|
-
next unless
|
38
|
+
next unless style_offense?(variable)
|
36
39
|
|
37
40
|
add_offense(
|
38
41
|
variable,
|
@@ -56,7 +59,7 @@ module RuboCop
|
|
56
59
|
end
|
57
60
|
end
|
58
61
|
|
59
|
-
def
|
62
|
+
def style_offense?(variable)
|
60
63
|
style == :symbols && string?(variable) ||
|
61
64
|
style == :strings && symbol?(variable)
|
62
65
|
end
|
@@ -42,15 +42,18 @@ module RuboCop
|
|
42
42
|
include ConfigurableNaming
|
43
43
|
include AllowedPattern
|
44
44
|
include Variable
|
45
|
+
include InsideExampleGroup
|
45
46
|
|
46
47
|
MSG = 'Use %<style>s for variable names.'
|
47
48
|
|
48
49
|
def on_send(node)
|
50
|
+
return unless inside_example_group?(node)
|
51
|
+
|
49
52
|
variable_definition?(node) do |variable|
|
50
53
|
return if variable.dstr_type? || variable.dsym_type?
|
51
54
|
return if matches_allowed_pattern?(variable.value)
|
52
55
|
|
53
|
-
check_name(node, variable.value, variable.
|
56
|
+
check_name(node, variable.value, variable.source_range)
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# Only investigates references that are one of the supported styles.
|
9
9
|
#
|
10
|
-
# @see https://
|
10
|
+
# @see https://rspec.info/features/3-12/rspec-mocks/verifying-doubles
|
11
11
|
#
|
12
12
|
# This cop can be configured in your configuration using the
|
13
13
|
# `EnforcedStyle` option and supports `--auto-gen-config`.
|
@@ -76,11 +76,11 @@ module RuboCop
|
|
76
76
|
break correct_style_detected unless opposing_style?(class_reference)
|
77
77
|
|
78
78
|
message = format(MSG, style: style)
|
79
|
-
expression = class_reference.
|
79
|
+
expression = class_reference.source_range
|
80
80
|
|
81
81
|
add_offense(expression, message: message) do |corrector|
|
82
|
-
|
83
|
-
corrector.replace(expression, correct_style(
|
82
|
+
offense = class_reference.source
|
83
|
+
corrector.replace(expression, correct_style(offense))
|
84
84
|
|
85
85
|
opposite_style_detected
|
86
86
|
end
|
@@ -98,11 +98,11 @@ module RuboCop
|
|
98
98
|
class_reference_style != style
|
99
99
|
end
|
100
100
|
|
101
|
-
def correct_style(
|
101
|
+
def correct_style(offense)
|
102
102
|
if style == :string
|
103
|
-
"'#{
|
103
|
+
"'#{offense}'"
|
104
104
|
else
|
105
|
-
|
105
|
+
offense.gsub(/^['"]|['"]$/, '')
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'rspec/capybara/current_path_expectation'
|
4
4
|
require_relative 'rspec/capybara/feature_methods'
|
5
|
+
require_relative 'rspec/capybara/match_style'
|
5
6
|
require_relative 'rspec/capybara/negation_matcher'
|
6
7
|
require_relative 'rspec/capybara/specific_actions'
|
7
8
|
require_relative 'rspec/capybara/specific_finders'
|
@@ -17,24 +18,29 @@ require_relative 'rspec/factory_bot/syntax_methods'
|
|
17
18
|
|
18
19
|
require_relative 'rspec/rails/avoid_setup_hook'
|
19
20
|
require_relative 'rspec/rails/have_http_status'
|
21
|
+
require_relative 'rspec/rails/negation_be_valid'
|
20
22
|
begin
|
21
23
|
require_relative 'rspec/rails/http_status'
|
22
24
|
rescue LoadError
|
23
25
|
# Rails/HttpStatus cannot be loaded if rack/utils is unavailable.
|
24
26
|
end
|
25
27
|
require_relative 'rspec/rails/inferred_spec_type'
|
28
|
+
require_relative 'rspec/rails/minitest_assertions'
|
29
|
+
require_relative 'rspec/rails/travel_around'
|
26
30
|
|
27
31
|
require_relative 'rspec/align_left_let_brace'
|
28
32
|
require_relative 'rspec/align_right_let_brace'
|
29
33
|
require_relative 'rspec/any_instance'
|
30
34
|
require_relative 'rspec/around_block'
|
31
35
|
require_relative 'rspec/be'
|
36
|
+
require_relative 'rspec/be_empty'
|
32
37
|
require_relative 'rspec/be_eq'
|
33
38
|
require_relative 'rspec/be_eql'
|
34
39
|
require_relative 'rspec/be_nil'
|
35
40
|
require_relative 'rspec/before_after_all'
|
36
41
|
require_relative 'rspec/change_by_zero'
|
37
42
|
require_relative 'rspec/class_check'
|
43
|
+
require_relative 'rspec/contain_exactly'
|
38
44
|
require_relative 'rspec/context_method'
|
39
45
|
require_relative 'rspec/context_wording'
|
40
46
|
require_relative 'rspec/describe_class'
|
@@ -51,6 +57,8 @@ require_relative 'rspec/empty_line_after_example_group'
|
|
51
57
|
require_relative 'rspec/empty_line_after_final_let'
|
52
58
|
require_relative 'rspec/empty_line_after_hook'
|
53
59
|
require_relative 'rspec/empty_line_after_subject'
|
60
|
+
require_relative 'rspec/empty_metadata'
|
61
|
+
require_relative 'rspec/eq'
|
54
62
|
require_relative 'rspec/example_length'
|
55
63
|
require_relative 'rspec/example_without_description'
|
56
64
|
require_relative 'rspec/example_wording'
|
@@ -67,6 +75,7 @@ require_relative 'rspec/identical_equality_assertion'
|
|
67
75
|
require_relative 'rspec/implicit_block_expectation'
|
68
76
|
require_relative 'rspec/implicit_expect'
|
69
77
|
require_relative 'rspec/implicit_subject'
|
78
|
+
require_relative 'rspec/indexed_let'
|
70
79
|
require_relative 'rspec/instance_spy'
|
71
80
|
require_relative 'rspec/instance_variable'
|
72
81
|
require_relative 'rspec/it_behaves_like'
|
@@ -75,9 +84,11 @@ require_relative 'rspec/leading_subject'
|
|
75
84
|
require_relative 'rspec/leaky_constant_declaration'
|
76
85
|
require_relative 'rspec/let_before_examples'
|
77
86
|
require_relative 'rspec/let_setup'
|
87
|
+
require_relative 'rspec/match_array'
|
78
88
|
require_relative 'rspec/message_chain'
|
79
89
|
require_relative 'rspec/message_expectation'
|
80
90
|
require_relative 'rspec/message_spies'
|
91
|
+
require_relative 'rspec/metadata_style'
|
81
92
|
require_relative 'rspec/missing_example_group_argument'
|
82
93
|
require_relative 'rspec/multiple_describes'
|
83
94
|
require_relative 'rspec/multiple_expectations'
|
@@ -92,7 +103,9 @@ require_relative 'rspec/pending'
|
|
92
103
|
require_relative 'rspec/pending_without_reason'
|
93
104
|
require_relative 'rspec/predicate_matcher'
|
94
105
|
require_relative 'rspec/receive_counts'
|
106
|
+
require_relative 'rspec/receive_messages'
|
95
107
|
require_relative 'rspec/receive_never'
|
108
|
+
require_relative 'rspec/redundant_around'
|
96
109
|
require_relative 'rspec/repeated_description'
|
97
110
|
require_relative 'rspec/repeated_example'
|
98
111
|
require_relative 'rspec/repeated_example_group_body'
|
@@ -104,7 +117,10 @@ require_relative 'rspec/scattered_setup'
|
|
104
117
|
require_relative 'rspec/shared_context'
|
105
118
|
require_relative 'rspec/shared_examples'
|
106
119
|
require_relative 'rspec/single_argument_message_chain'
|
120
|
+
require_relative 'rspec/skip_block_inside_example'
|
107
121
|
require_relative 'rspec/sort_metadata'
|
122
|
+
require_relative 'rspec/spec_file_path_format'
|
123
|
+
require_relative 'rspec/spec_file_path_suffix'
|
108
124
|
require_relative 'rspec/stubbed_mock'
|
109
125
|
require_relative 'rspec/subject_declaration'
|
110
126
|
require_relative 'rspec/subject_stub'
|
@@ -8,6 +8,21 @@ module RuboCop
|
|
8
8
|
class ConfigFormatter
|
9
9
|
EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
|
10
10
|
SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails)
|
11
|
+
EXTRACTED_COPS = %(
|
12
|
+
RSpec/Capybara/CurrentPathExpectation
|
13
|
+
RSpec/Capybara/MatchStyle
|
14
|
+
RSpec/Capybara/NegationMatcher
|
15
|
+
RSpec/Capybara/SpecificActions
|
16
|
+
RSpec/Capybara/SpecificFinders
|
17
|
+
RSpec/Capybara/SpecificMatcher
|
18
|
+
RSpec/Capybara/VisibilityMatcher
|
19
|
+
RSpec/FactoryBot/AttributeDefinedStatically
|
20
|
+
RSpec/FactoryBot/ConsistentParenthesesStyle
|
21
|
+
RSpec/FactoryBot/CreateList
|
22
|
+
RSpec/FactoryBot/FactoryClassName
|
23
|
+
RSpec/FactoryBot/FactoryNameStyle
|
24
|
+
RSpec/FactoryBot/SyntaxMethods
|
25
|
+
)
|
11
26
|
AMENDMENTS = %(Metrics/BlockLength)
|
12
27
|
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
|
13
28
|
|
@@ -29,6 +44,7 @@ module RuboCop
|
|
29
44
|
def unified_config
|
30
45
|
cops.each_with_object(config.dup) do |cop, unified|
|
31
46
|
next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
|
47
|
+
next if EXTRACTED_COPS.include?(cop)
|
32
48
|
|
33
49
|
replace_nil(unified[cop])
|
34
50
|
unified[cop].merge!(descriptions.fetch(cop))
|
@@ -10,14 +10,12 @@ module RuboCop
|
|
10
10
|
#
|
11
11
|
# Selectors which indicate that we should stop searching
|
12
12
|
#
|
13
|
-
def_node_matcher :scope_change?,
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}
|
20
|
-
PATTERN
|
13
|
+
def_node_matcher :scope_change?, <<~PATTERN
|
14
|
+
(block {
|
15
|
+
(send #rspec? {#SharedGroups.all #ExampleGroups.all} ...)
|
16
|
+
(send nil? #Includes.all ...)
|
17
|
+
} ...)
|
18
|
+
PATTERN
|
21
19
|
|
22
20
|
def lets
|
23
21
|
find_all_in_scope(node, :let?)
|
@@ -4,18 +4,44 @@ module RuboCop
|
|
4
4
|
module RSpec
|
5
5
|
module Language
|
6
6
|
# Helper methods to detect RSpec DSL used with send and block
|
7
|
+
# @deprecated Prefer using Node Pattern directly
|
8
|
+
# Use `'(block (send nil? #Example.all ...) ...)'` instead of
|
9
|
+
# `block_pattern('#Example.all')`
|
7
10
|
module NodePattern
|
11
|
+
# @deprecated Prefer using Node Pattern directly
|
8
12
|
def send_pattern(string)
|
13
|
+
deprecation_warning __method__
|
9
14
|
"(send #rspec? #{string} ...)"
|
10
15
|
end
|
11
16
|
|
17
|
+
# @deprecated Prefer using Node Pattern directly
|
12
18
|
def block_pattern(string)
|
19
|
+
deprecation_warning __method__
|
13
20
|
"(block #{send_pattern(string)} ...)"
|
14
21
|
end
|
15
22
|
|
23
|
+
# @deprecated Prefer using Node Pattern directly
|
16
24
|
def numblock_pattern(string)
|
25
|
+
deprecation_warning __method__
|
17
26
|
"(numblock #{send_pattern(string)} ...)"
|
18
27
|
end
|
28
|
+
|
29
|
+
# @deprecated Prefer using Node Pattern directly
|
30
|
+
def block_or_numblock_pattern(string)
|
31
|
+
deprecation_warning __method__
|
32
|
+
"{#{block_pattern(string)} #{numblock_pattern(string)}}"
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def deprecation_warning(method)
|
38
|
+
# Only warn in derived extensions' specs
|
39
|
+
return unless defined?(::RSpec)
|
40
|
+
|
41
|
+
Kernel.warn <<~MESSAGE, uplevel: 2
|
42
|
+
Usage of #{method} is deprecated. Use node pattern explicitly.
|
43
|
+
MESSAGE
|
44
|
+
end
|
19
45
|
end
|
20
46
|
end
|
21
47
|
end
|
@@ -20,52 +20,61 @@ module RuboCop
|
|
20
20
|
end
|
21
21
|
|
22
22
|
# @!method rspec?(node)
|
23
|
-
def_node_matcher :rspec?, '{
|
23
|
+
def_node_matcher :rspec?, '{#explicit_rspec? nil?}'
|
24
|
+
|
25
|
+
# @!method explicit_rspec?(node)
|
26
|
+
def_node_matcher :explicit_rspec?, '(const {nil? cbase} :RSpec)'
|
24
27
|
|
25
28
|
# @!method example_group?(node)
|
26
|
-
def_node_matcher :example_group?,
|
29
|
+
def_node_matcher :example_group?, <<~PATTERN
|
30
|
+
({block numblock} (send #rspec? #ExampleGroups.all ...) ...)
|
31
|
+
PATTERN
|
27
32
|
|
28
33
|
# @!method shared_group?(node)
|
29
|
-
def_node_matcher :shared_group?,
|
34
|
+
def_node_matcher :shared_group?,
|
35
|
+
'(block (send #rspec? #SharedGroups.all ...) ...)'
|
30
36
|
|
31
37
|
# @!method spec_group?(node)
|
32
|
-
def_node_matcher :spec_group?,
|
33
|
-
|
38
|
+
def_node_matcher :spec_group?, <<~PATTERN
|
39
|
+
({block numblock} (send #rspec?
|
40
|
+
{#SharedGroups.all #ExampleGroups.all}
|
41
|
+
...) ...)
|
42
|
+
PATTERN
|
34
43
|
|
35
44
|
# @!method example_group_with_body?(node)
|
36
45
|
def_node_matcher :example_group_with_body?, <<-PATTERN
|
37
|
-
(block
|
46
|
+
(block (send #rspec? #ExampleGroups.all ...) args !nil?)
|
38
47
|
PATTERN
|
39
48
|
|
40
49
|
# @!method example?(node)
|
41
|
-
def_node_matcher :example?,
|
50
|
+
def_node_matcher :example?, '(block (send nil? #Examples.all ...) ...)'
|
42
51
|
|
43
52
|
# @!method hook?(node)
|
44
53
|
def_node_matcher :hook?, <<-PATTERN
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
54
|
+
{
|
55
|
+
(numblock (send nil? #Hooks.all ...) ...)
|
56
|
+
(block (send nil? #Hooks.all ...) ...)
|
57
|
+
}
|
49
58
|
PATTERN
|
50
59
|
|
51
60
|
# @!method let?(node)
|
52
61
|
def_node_matcher :let?, <<-PATTERN
|
53
62
|
{
|
54
|
-
|
55
|
-
(send
|
63
|
+
(block (send nil? #Helpers.all ...) ...)
|
64
|
+
(send nil? #Helpers.all _ block_pass)
|
56
65
|
}
|
57
66
|
PATTERN
|
58
67
|
|
59
68
|
# @!method include?(node)
|
60
69
|
def_node_matcher :include?, <<-PATTERN
|
61
70
|
{
|
62
|
-
|
63
|
-
|
71
|
+
(block (send nil? #Includes.all ...) ...)
|
72
|
+
(send nil? #Includes.all ...)
|
64
73
|
}
|
65
74
|
PATTERN
|
66
75
|
|
67
76
|
# @!method subject?(node)
|
68
|
-
def_node_matcher :subject?,
|
77
|
+
def_node_matcher :subject?, '(block (send nil? #Subjects.all ...) ...)'
|
69
78
|
|
70
79
|
module ExampleGroups # :nodoc:
|
71
80
|
class << self
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -4,6 +4,8 @@ require 'pathname'
|
|
4
4
|
require 'yaml'
|
5
5
|
|
6
6
|
require 'rubocop'
|
7
|
+
require 'rubocop-capybara'
|
8
|
+
require 'rubocop-factory_bot'
|
7
9
|
|
8
10
|
require_relative 'rubocop/rspec'
|
9
11
|
require_relative 'rubocop/rspec/inject'
|
@@ -15,12 +17,10 @@ require_relative 'rubocop/rspec/wording'
|
|
15
17
|
# Dependent on `RuboCop::RSpec::Language::NodePattern`.
|
16
18
|
require_relative 'rubocop/rspec/language'
|
17
19
|
|
18
|
-
require_relative 'rubocop/rspec/
|
19
|
-
|
20
|
-
require_relative 'rubocop/cop/rspec/mixin/capybara_help'
|
21
|
-
require_relative 'rubocop/cop/rspec/mixin/css_selector'
|
20
|
+
require_relative 'rubocop/cop/rspec/mixin/file_help'
|
22
21
|
require_relative 'rubocop/cop/rspec/mixin/final_end_location'
|
23
22
|
require_relative 'rubocop/cop/rspec/mixin/inside_example_group'
|
23
|
+
require_relative 'rubocop/cop/rspec/mixin/location_help'
|
24
24
|
require_relative 'rubocop/cop/rspec/mixin/metadata'
|
25
25
|
require_relative 'rubocop/cop/rspec/mixin/namespace'
|
26
26
|
require_relative 'rubocop/cop/rspec/mixin/skip_or_pending'
|
@@ -37,7 +37,6 @@ require_relative 'rubocop/rspec/concept'
|
|
37
37
|
require_relative 'rubocop/rspec/corrector/move_node'
|
38
38
|
require_relative 'rubocop/rspec/example'
|
39
39
|
require_relative 'rubocop/rspec/example_group'
|
40
|
-
require_relative 'rubocop/rspec/factory_bot'
|
41
40
|
require_relative 'rubocop/rspec/hook'
|
42
41
|
|
43
42
|
RuboCop::RSpec::Inject.defaults!
|