rubocop-rspec 2.16.0 → 2.24.1
Sign up to get free protection for your applications and to get access to all the features.
- 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!
|