rubocop-rspec 2.14.2 → 2.16.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 +24 -0
- data/config/default.yml +48 -29
- data/lib/rubocop/cop/rspec/be.rb +2 -0
- data/lib/rubocop/cop/rspec/be_eq.rb +3 -0
- data/lib/rubocop/cop/rspec/be_eql.rb +3 -0
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +3 -3
- data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +3 -5
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +58 -0
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +2 -0
- data/lib/rubocop/cop/rspec/expect_actual.rb +2 -0
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +16 -9
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +9 -2
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +74 -0
- data/lib/rubocop/cop/rspec/implicit_expect.rb +2 -0
- data/lib/rubocop/cop/rspec/leading_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/message_spies.rb +2 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +49 -0
- data/lib/rubocop/cop/rspec/named_subject.rb +81 -6
- data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +123 -0
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +2 -0
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +5 -2
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_description.rb +25 -2
- data/lib/rubocop/cop/rspec/scattered_setup.rb +2 -0
- data/lib/rubocop/cop/rspec/sort_metadata.rb +4 -35
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +2 -0
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -0
- data/lib/rubocop/cop/rspec_cops.rb +3 -0
- data/lib/rubocop/rspec/config_formatter.rb +2 -2
- data/lib/rubocop/rspec/description_extractor.rb +5 -10
- data/lib/rubocop/rspec/language.rb +9 -3
- 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.rb +18 -13
- metadata +7 -2
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Helper methods to find RSpec metadata.
|
7
|
+
module Metadata
|
8
|
+
extend RuboCop::NodePattern::Macros
|
9
|
+
|
10
|
+
include RuboCop::RSpec::Language
|
11
|
+
|
12
|
+
# @!method rspec_metadata(node)
|
13
|
+
def_node_matcher :rspec_metadata, <<~PATTERN
|
14
|
+
(block
|
15
|
+
(send
|
16
|
+
#rspec? {#Examples.all #ExampleGroups.all #SharedGroups.all #Hooks.all} _ ${send str sym}* (hash $...)?)
|
17
|
+
...)
|
18
|
+
PATTERN
|
19
|
+
|
20
|
+
# @!method rspec_configure(node)
|
21
|
+
def_node_matcher :rspec_configure, <<~PATTERN
|
22
|
+
(block (send #rspec? :configure) (args (arg $_)) ...)
|
23
|
+
PATTERN
|
24
|
+
|
25
|
+
# @!method metadata_in_block(node)
|
26
|
+
def_node_search :metadata_in_block, <<~PATTERN
|
27
|
+
(send (lvar %) #Hooks.all _ ${send str sym}* (hash $...)?)
|
28
|
+
PATTERN
|
29
|
+
|
30
|
+
def on_block(node)
|
31
|
+
rspec_configure(node) do |block_var|
|
32
|
+
metadata_in_block(node, block_var) do |symbols, pairs|
|
33
|
+
on_metadata(symbols, pairs.flatten)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
rspec_metadata(node) do |symbols, pairs|
|
38
|
+
on_metadata(symbols, pairs.flatten)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias on_numblock on_block
|
42
|
+
|
43
|
+
def on_metadata(_symbols, _pairs)
|
44
|
+
raise ::NotImplementedError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -12,11 +12,11 @@ module RuboCop
|
|
12
12
|
# should be the most important object in your tests so they deserve
|
13
13
|
# a descriptive name.
|
14
14
|
#
|
15
|
-
# This cop can be configured in your configuration using
|
16
|
-
# `IgnoreSharedExamples` which will not report offenses for implicit
|
15
|
+
# This cop can be configured in your configuration using `EnforcedStyle`,
|
16
|
+
# and `IgnoreSharedExamples` which will not report offenses for implicit
|
17
17
|
# subjects in shared example groups.
|
18
18
|
#
|
19
|
-
# @example
|
19
|
+
# @example `EnforcedStyle: always` (default)
|
20
20
|
# # bad
|
21
21
|
# RSpec.describe User do
|
22
22
|
# subject { described_class.new }
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
# end
|
28
28
|
#
|
29
29
|
# # good
|
30
|
-
# RSpec.describe
|
30
|
+
# RSpec.describe User do
|
31
31
|
# subject(:user) { described_class.new }
|
32
32
|
#
|
33
33
|
# it 'is valid' do
|
@@ -36,13 +36,49 @@ module RuboCop
|
|
36
36
|
# end
|
37
37
|
#
|
38
38
|
# # also good
|
39
|
-
# RSpec.describe
|
39
|
+
# RSpec.describe User do
|
40
|
+
# subject(:user) { described_class.new }
|
41
|
+
#
|
42
|
+
# it { is_expected.to be_valid }
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# @example `EnforcedStyle: named_only`
|
46
|
+
# # bad
|
47
|
+
# RSpec.describe User do
|
48
|
+
# subject(:user) { described_class.new }
|
49
|
+
#
|
50
|
+
# it 'is valid' do
|
51
|
+
# expect(subject.valid?).to be(true)
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# # good
|
56
|
+
# RSpec.describe User do
|
40
57
|
# subject(:user) { described_class.new }
|
41
58
|
#
|
59
|
+
# it 'is valid' do
|
60
|
+
# expect(user.valid?).to be(true)
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# # also good
|
65
|
+
# RSpec.describe User do
|
66
|
+
# subject { described_class.new }
|
67
|
+
#
|
42
68
|
# it { is_expected.to be_valid }
|
43
69
|
# end
|
44
70
|
#
|
71
|
+
# # acceptable
|
72
|
+
# RSpec.describe User do
|
73
|
+
# subject { described_class.new }
|
74
|
+
#
|
75
|
+
# it 'is valid' do
|
76
|
+
# expect(subject.valid?).to be(true)
|
77
|
+
# end
|
78
|
+
# end
|
45
79
|
class NamedSubject < Base
|
80
|
+
include ConfigurableEnforcedStyle
|
81
|
+
|
46
82
|
MSG = 'Name your test subject if you need to reference it explicitly.'
|
47
83
|
|
48
84
|
# @!method example_or_hook_block?(node)
|
@@ -62,14 +98,53 @@ module RuboCop
|
|
62
98
|
end
|
63
99
|
|
64
100
|
subject_usage(node) do |subject_node|
|
65
|
-
|
101
|
+
check_explicit_subject(subject_node)
|
66
102
|
end
|
67
103
|
end
|
68
104
|
|
105
|
+
private
|
106
|
+
|
69
107
|
def ignored_shared_example?(node)
|
70
108
|
cop_config['IgnoreSharedExamples'] &&
|
71
109
|
node.each_ancestor(:block).any?(&method(:shared_example?))
|
72
110
|
end
|
111
|
+
|
112
|
+
def check_explicit_subject(node)
|
113
|
+
return if allow_explicit_subject?(node)
|
114
|
+
|
115
|
+
add_offense(node.loc.selector)
|
116
|
+
end
|
117
|
+
|
118
|
+
def allow_explicit_subject?(node)
|
119
|
+
!always? && !named_only?(node)
|
120
|
+
end
|
121
|
+
|
122
|
+
def always?
|
123
|
+
style == :always
|
124
|
+
end
|
125
|
+
|
126
|
+
def named_only?(node)
|
127
|
+
style == :named_only &&
|
128
|
+
subject_definition_is_named?(node)
|
129
|
+
end
|
130
|
+
|
131
|
+
def subject_definition_is_named?(node)
|
132
|
+
subject = nearest_subject(node)
|
133
|
+
|
134
|
+
subject&.send_node&.arguments?
|
135
|
+
end
|
136
|
+
|
137
|
+
def nearest_subject(node)
|
138
|
+
node
|
139
|
+
.each_ancestor(:block)
|
140
|
+
.lazy
|
141
|
+
.map { |block_node| find_subject(block_node) }
|
142
|
+
.find(&:itself)
|
143
|
+
end
|
144
|
+
|
145
|
+
def find_subject(block_node)
|
146
|
+
block_node.body.child_nodes.find { |send_node| subject?(send_node) }
|
147
|
+
end
|
73
148
|
end
|
74
149
|
end
|
75
150
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for pending or skipped examples without reason.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# pending 'does something' do
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# it 'does something', :pending do
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# it 'does something' do
|
19
|
+
# pending
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# xdescribe 'something' do
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # bad
|
27
|
+
# skip 'does something' do
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# # bad
|
31
|
+
# it 'does something', :skip do
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# # bad
|
35
|
+
# it 'does something' do
|
36
|
+
# skip
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# # bad
|
40
|
+
# it 'does something'
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# it 'does something' do
|
44
|
+
# pending 'reason'
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# # good
|
48
|
+
# it 'does something' do
|
49
|
+
# skip 'reason'
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# # good
|
53
|
+
# it 'does something', pending: 'reason' do
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# # good
|
57
|
+
# it 'does something', skip: 'reason' do
|
58
|
+
# end
|
59
|
+
class PendingWithoutReason < Base
|
60
|
+
MSG = 'Give the reason for pending or skip.'
|
61
|
+
|
62
|
+
# @!method pending_by_example_method?(node)
|
63
|
+
def_node_matcher :pending_by_example_method?, block_pattern(<<~PATTERN)
|
64
|
+
#Examples.pending
|
65
|
+
PATTERN
|
66
|
+
|
67
|
+
# @!method pending_by_metadata_without_reason?(node)
|
68
|
+
def_node_matcher :pending_by_metadata_without_reason?, <<~PATTERN
|
69
|
+
(send #rspec? {#ExampleGroups.all #Examples.all} ... {<(sym :pending) ...> (hash <(pair (sym :pending) true) ...>)})
|
70
|
+
PATTERN
|
71
|
+
|
72
|
+
# @!method skipped_by_example_method?(node)
|
73
|
+
def_node_matcher :skipped_by_example_method?, block_pattern(<<~PATTERN)
|
74
|
+
#Examples.skipped
|
75
|
+
PATTERN
|
76
|
+
|
77
|
+
# @!method skipped_by_example_group_method?(node)
|
78
|
+
def_node_matcher(
|
79
|
+
:skipped_by_example_group_method?,
|
80
|
+
block_pattern(<<~PATTERN)
|
81
|
+
#ExampleGroups.skipped
|
82
|
+
PATTERN
|
83
|
+
)
|
84
|
+
|
85
|
+
# @!method skipped_by_metadata_without_reason?(node)
|
86
|
+
def_node_matcher :skipped_by_metadata_without_reason?, <<~PATTERN
|
87
|
+
(send #rspec? {#ExampleGroups.all #Examples.all} ... {<(sym :skip) ...> (hash <(pair (sym :skip) true) ...>)})
|
88
|
+
PATTERN
|
89
|
+
|
90
|
+
def on_send(node)
|
91
|
+
if pending_without_reason?(node)
|
92
|
+
add_offense(node, message: 'Give the reason for pending.')
|
93
|
+
elsif skipped_without_reason?(node)
|
94
|
+
add_offense(node, message: 'Give the reason for skip.')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def pending_by_pending_step_without_reason?(node)
|
101
|
+
node.method?(:pending) && node.first_argument.nil?
|
102
|
+
end
|
103
|
+
|
104
|
+
def pending_without_reason?(node)
|
105
|
+
pending_by_example_method?(node.block_node) ||
|
106
|
+
pending_by_metadata_without_reason?(node) ||
|
107
|
+
pending_by_pending_step_without_reason?(node)
|
108
|
+
end
|
109
|
+
|
110
|
+
def skipped_by_skip_step_without_reason?(node)
|
111
|
+
node.method?(:skip) && node.first_argument.nil?
|
112
|
+
end
|
113
|
+
|
114
|
+
def skipped_without_reason?(node)
|
115
|
+
skipped_by_example_group_method?(node.block_node) ||
|
116
|
+
skipped_by_example_method?(node.block_node) ||
|
117
|
+
skipped_by_metadata_without_reason?(node) ||
|
118
|
+
skipped_by_skip_step_without_reason?(node)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -13,20 +13,23 @@ module RuboCop
|
|
13
13
|
# # good
|
14
14
|
# expect(response).to have_http_status(200)
|
15
15
|
#
|
16
|
-
class HaveHttpStatus < Base
|
16
|
+
class HaveHttpStatus < ::RuboCop::Cop::Base
|
17
17
|
extend AutoCorrector
|
18
18
|
|
19
19
|
MSG =
|
20
20
|
'Prefer `expect(response).%<to>s have_http_status(%<status>i)` ' \
|
21
21
|
'over `expect(response.status).%<to>s %<match>s`.'
|
22
22
|
|
23
|
+
RUNNERS = %i[to to_not not_to].to_set
|
24
|
+
RESTRICT_ON_SEND = RUNNERS
|
25
|
+
|
23
26
|
# @!method match_status(node)
|
24
27
|
def_node_matcher :match_status, <<-PATTERN
|
25
28
|
(send
|
26
29
|
(send nil? :expect
|
27
30
|
$(send (send nil? :response) :status)
|
28
31
|
)
|
29
|
-
|
32
|
+
$RUNNERS
|
30
33
|
$(send nil? {:be :eq :eql :equal} (int $_))
|
31
34
|
)
|
32
35
|
PATTERN
|
@@ -45,8 +45,12 @@ module RuboCop
|
|
45
45
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
46
46
|
return unless example_group?(node)
|
47
47
|
|
48
|
-
repeated_descriptions(node).each do |
|
49
|
-
add_offense(
|
48
|
+
repeated_descriptions(node).each do |description|
|
49
|
+
add_offense(description)
|
50
|
+
end
|
51
|
+
|
52
|
+
repeated_its(node).each do |its|
|
53
|
+
add_offense(its)
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
@@ -57,6 +61,7 @@ module RuboCop
|
|
57
61
|
grouped_examples =
|
58
62
|
RuboCop::RSpec::ExampleGroup.new(node)
|
59
63
|
.examples
|
64
|
+
.reject { |n| n.definition.method?(:its) }
|
60
65
|
.group_by { |example| example_signature(example) }
|
61
66
|
|
62
67
|
grouped_examples
|
@@ -66,9 +71,27 @@ module RuboCop
|
|
66
71
|
.map(&:definition)
|
67
72
|
end
|
68
73
|
|
74
|
+
def repeated_its(node)
|
75
|
+
grouped_its =
|
76
|
+
RuboCop::RSpec::ExampleGroup.new(node)
|
77
|
+
.examples
|
78
|
+
.select { |n| n.definition.method?(:its) }
|
79
|
+
.group_by { |example| its_signature(example) }
|
80
|
+
|
81
|
+
grouped_its
|
82
|
+
.select { |signatures, group| signatures.any? && group.size > 1 }
|
83
|
+
.values
|
84
|
+
.flatten
|
85
|
+
.map(&:to_node)
|
86
|
+
end
|
87
|
+
|
69
88
|
def example_signature(example)
|
70
89
|
[example.metadata, example.doc_string]
|
71
90
|
end
|
91
|
+
|
92
|
+
def its_signature(example)
|
93
|
+
[example.doc_string, example]
|
94
|
+
end
|
72
95
|
end
|
73
96
|
end
|
74
97
|
end
|
@@ -18,45 +18,12 @@ module RuboCop
|
|
18
18
|
#
|
19
19
|
class SortMetadata < Base
|
20
20
|
extend AutoCorrector
|
21
|
+
include Metadata
|
21
22
|
include RangeHelp
|
22
23
|
|
23
24
|
MSG = 'Sort metadata alphabetically.'
|
24
25
|
|
25
|
-
|
26
|
-
def_node_matcher :rspec_metadata, <<~PATTERN
|
27
|
-
(block
|
28
|
-
(send
|
29
|
-
#rspec? {#Examples.all #ExampleGroups.all #SharedGroups.all #Hooks.all} _ ${send str sym}* (hash $...)?)
|
30
|
-
...)
|
31
|
-
PATTERN
|
32
|
-
|
33
|
-
# @!method rspec_configure(node)
|
34
|
-
def_node_matcher :rspec_configure, <<~PATTERN
|
35
|
-
(block (send #rspec? :configure) (args (arg $_)) ...)
|
36
|
-
PATTERN
|
37
|
-
|
38
|
-
# @!method metadata_in_block(node)
|
39
|
-
def_node_search :metadata_in_block, <<~PATTERN
|
40
|
-
(send (lvar %) #Hooks.all _ ${send str sym}* (hash $...)?)
|
41
|
-
PATTERN
|
42
|
-
|
43
|
-
def on_block(node)
|
44
|
-
rspec_configure(node) do |block_var|
|
45
|
-
metadata_in_block(node, block_var) do |symbols, pairs|
|
46
|
-
investigate(symbols, pairs.flatten)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
rspec_metadata(node) do |symbols, pairs|
|
51
|
-
investigate(symbols, pairs.flatten)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
alias on_numblock on_block
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def investigate(symbols, pairs)
|
26
|
+
def on_metadata(symbols, pairs)
|
60
27
|
return if sorted?(symbols, pairs)
|
61
28
|
|
62
29
|
crime_scene = crime_scene(symbols, pairs)
|
@@ -65,6 +32,8 @@ module RuboCop
|
|
65
32
|
end
|
66
33
|
end
|
67
34
|
|
35
|
+
private
|
36
|
+
|
68
37
|
def crime_scene(symbols, pairs)
|
69
38
|
metadata = symbols + pairs
|
70
39
|
|
@@ -12,6 +12,7 @@ require_relative 'rspec/factory_bot/attribute_defined_statically'
|
|
12
12
|
require_relative 'rspec/factory_bot/consistent_parentheses_style'
|
13
13
|
require_relative 'rspec/factory_bot/create_list'
|
14
14
|
require_relative 'rspec/factory_bot/factory_class_name'
|
15
|
+
require_relative 'rspec/factory_bot/factory_name_style'
|
15
16
|
require_relative 'rspec/factory_bot/syntax_methods'
|
16
17
|
|
17
18
|
require_relative 'rspec/rails/avoid_setup_hook'
|
@@ -42,6 +43,7 @@ require_relative 'rspec/describe_symbol'
|
|
42
43
|
require_relative 'rspec/described_class'
|
43
44
|
require_relative 'rspec/described_class_module_wrapping'
|
44
45
|
require_relative 'rspec/dialect'
|
46
|
+
require_relative 'rspec/duplicated_metadata'
|
45
47
|
require_relative 'rspec/empty_example_group'
|
46
48
|
require_relative 'rspec/empty_hook'
|
47
49
|
require_relative 'rspec/empty_line_after_example'
|
@@ -87,6 +89,7 @@ require_relative 'rspec/no_expectation_example'
|
|
87
89
|
require_relative 'rspec/not_to_not'
|
88
90
|
require_relative 'rspec/overwriting_setup'
|
89
91
|
require_relative 'rspec/pending'
|
92
|
+
require_relative 'rspec/pending_without_reason'
|
90
93
|
require_relative 'rspec/predicate_matcher'
|
91
94
|
require_relative 'rspec/receive_counts'
|
92
95
|
require_relative 'rspec/receive_never'
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
9
9
|
EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
|
10
10
|
SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails)
|
11
11
|
AMENDMENTS = %(Metrics/BlockLength)
|
12
|
-
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/
|
12
|
+
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
|
13
13
|
|
14
14
|
def initialize(config, descriptions)
|
15
15
|
@config = config
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def reference(cop)
|
50
|
-
COP_DOC_BASE_URL + cop
|
50
|
+
COP_DOC_BASE_URL + cop
|
51
51
|
end
|
52
52
|
|
53
53
|
attr_reader :config, :descriptions
|
@@ -21,7 +21,8 @@ module RuboCop
|
|
21
21
|
|
22
22
|
# Decorator of a YARD code object for working with documented rspec cops
|
23
23
|
class CodeObject
|
24
|
-
|
24
|
+
RSPEC_COP_CLASS_NAME = 'RuboCop::Cop::RSpec::Base'
|
25
|
+
RUBOCOP_COP_CLASS_NAME = 'RuboCop::Cop::Base'
|
25
26
|
RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec'
|
26
27
|
|
27
28
|
def initialize(yardoc)
|
@@ -32,10 +33,7 @@ module RuboCop
|
|
32
33
|
#
|
33
34
|
# @return [Boolean]
|
34
35
|
def rspec_cop?
|
35
|
-
|
36
|
-
rspec_cop_namespace? &&
|
37
|
-
cop_subclass? &&
|
38
|
-
!abstract?
|
36
|
+
cop_subclass? && !abstract? && rspec_cop_namespace?
|
39
37
|
end
|
40
38
|
|
41
39
|
# Configuration for the documented cop that would live in default.yml
|
@@ -55,10 +53,6 @@ module RuboCop
|
|
55
53
|
yardoc.docstring.split("\n\n").first.to_s
|
56
54
|
end
|
57
55
|
|
58
|
-
def class_documentation?
|
59
|
-
yardoc.type.equal?(:class)
|
60
|
-
end
|
61
|
-
|
62
56
|
def rspec_cop_namespace?
|
63
57
|
documented_constant.start_with?(RSPEC_NAMESPACE)
|
64
58
|
end
|
@@ -68,7 +62,8 @@ module RuboCop
|
|
68
62
|
end
|
69
63
|
|
70
64
|
def cop_subclass?
|
71
|
-
yardoc.superclass.path ==
|
65
|
+
yardoc.superclass.path == RSPEC_COP_CLASS_NAME ||
|
66
|
+
yardoc.superclass.path == RUBOCOP_COP_CLASS_NAME
|
72
67
|
end
|
73
68
|
|
74
69
|
def abstract?
|
@@ -135,8 +135,9 @@ module RuboCop
|
|
135
135
|
end
|
136
136
|
|
137
137
|
module HookScopes # :nodoc:
|
138
|
+
ALL = %i[each example context all suite].freeze
|
138
139
|
def self.all(element)
|
139
|
-
|
140
|
+
ALL.include?(element)
|
140
141
|
end
|
141
142
|
end
|
142
143
|
|
@@ -158,8 +159,13 @@ module RuboCop
|
|
158
159
|
end
|
159
160
|
|
160
161
|
module Runners # :nodoc:
|
161
|
-
|
162
|
-
|
162
|
+
ALL = %i[to to_not not_to].freeze
|
163
|
+
class << self
|
164
|
+
def all(element = nil)
|
165
|
+
return ALL if element.nil?
|
166
|
+
|
167
|
+
ALL.include?(element)
|
168
|
+
end
|
163
169
|
end
|
164
170
|
end
|
165
171
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.shared_context 'with default RSpec/Language config' do
|
4
|
+
include_context 'config'
|
5
|
+
|
6
|
+
# Deep duplication is needed to prevent config leakage between examples
|
7
|
+
let(:other_cops) do
|
8
|
+
default_language = RuboCop::ConfigLoader
|
9
|
+
.default_configuration['RSpec']['Language']
|
10
|
+
default_include = RuboCop::ConfigLoader
|
11
|
+
.default_configuration['RSpec']['Include']
|
12
|
+
{ 'RSpec' =>
|
13
|
+
{
|
14
|
+
'Include' => default_include,
|
15
|
+
'Language' => deep_dup(default_language)
|
16
|
+
} }
|
17
|
+
end
|
18
|
+
|
19
|
+
def deep_dup(object)
|
20
|
+
case object
|
21
|
+
when Array
|
22
|
+
object.map { |item| deep_dup(item) }
|
23
|
+
when Hash
|
24
|
+
object.transform_values(&method(:deep_dup))
|
25
|
+
else
|
26
|
+
object # only collections undergo modifications and need duping
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|