rubocop-rspec 2.14.2 → 2.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/config/default.yml +5 -12
- data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +11 -6
- 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/repeated_description.rb +25 -2
- data/lib/rubocop/rspec/language.rb +4 -2
- data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +29 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e120f8d06ef760cbe4f3a3d077ca6cd8ceeb274a26042a6e1469fe9a280c969
|
4
|
+
data.tar.gz: 0c80cc155e8f64b03a97de1327e454d9ff2efb1a75b02e3b098f868afed30d17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e982f97a23de2473c5cae6cd20bb653bcbcee806abddf0dda09c7b30692193858fc105c7b46ce3c004f28a7f680d1b3a475298c7b10d0e1499d5b80333fde504
|
7
|
+
data.tar.gz: c3b79b39a2c98d9103cb4edbf6c2d8e2cc957790fd8fa617e1fdece172f3dfaaf652bf482e7236a1da663f3b9afae943c17efee1e4a5f0293acc771bbc1c3c43
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.15.0 (2022-11-03)
|
6
|
+
|
7
|
+
- Fix a false positive for `RSpec/RepeatedDescription` when different its block expectations are used. ([@ydah])
|
8
|
+
- Add `named_only` style to `RSpec/NamedSubject`. ([@kuahyeow])
|
9
|
+
- Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls without the first positional argument. ([@pirj])
|
10
|
+
- Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls inside a Hash or an Array. ([@pirj])
|
11
|
+
- Fix `RSpec/NestedGroups` to correctly use `AllowedGroups` config. ([@samrjenkins])
|
12
|
+
- Remove `Runners` and `HookScopes` RSpec DSL elements from configuration. ([@pirj])
|
13
|
+
- Add `with default RSpec/Language config` helper to `lib` (under `rubocop/rspec/shared_contexts/default_rspec_language_config_context`), to allow use for downstream cops based on `RuboCop::Cop::RSpec::Base`. ([@smcgivern])
|
14
|
+
|
5
15
|
## 2.14.2 (2022-10-25)
|
6
16
|
|
7
17
|
- Fix an incorrect autocorrect for `FactoryBot/ConsistentParenthesesStyle` with `omit_parentheses` option when method name and first argument are not on same line. ([@ydah])
|
@@ -724,6 +734,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
724
734
|
[@jtannas]: https://github.com/jtannas
|
725
735
|
[@kellysutton]: https://github.com/kellysutton
|
726
736
|
[@koic]: https://github.com/koic
|
737
|
+
[@kuahyeow]: https://github.com/kuahyeow
|
727
738
|
[@lazycoder9]: https://github.com/lazycoder9
|
728
739
|
[@leoarnold]: https://github.com/leoarnold
|
729
740
|
[@liberatys]: https://github.com/Liberatys
|
@@ -760,9 +771,11 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
760
771
|
[@rrosenblum]: https://github.com/rrosenblum
|
761
772
|
[@rspeicher]: https://github.com/rspeicher
|
762
773
|
[@rst-j]: https://github.com/RST-J
|
774
|
+
[@samrjenkins]: https://github.com/samrjenkins
|
763
775
|
[@schmijos]: https://github.com/schmijos
|
764
776
|
[@seanpdoyle]: https://github.com/seanpdoyle
|
765
777
|
[@sl4vr]: https://github.com/sl4vr
|
778
|
+
[@smcgivern]: https://github.com/smcgivern
|
766
779
|
[@stephannv]: https://github.com/stephannv
|
767
780
|
[@t3h2mas]: https://github.com/t3h2mas
|
768
781
|
[@tdeo]: https://github.com/tdeo
|
data/config/default.yml
CHANGED
@@ -12,8 +12,6 @@ RSpec:
|
|
12
12
|
- Expectations
|
13
13
|
- Helpers
|
14
14
|
- Hooks
|
15
|
-
- HookScopes
|
16
|
-
- Runners
|
17
15
|
- Subjects
|
18
16
|
ExampleGroups:
|
19
17
|
inherit_mode:
|
@@ -81,12 +79,6 @@ RSpec:
|
|
81
79
|
- prepend_after
|
82
80
|
- after
|
83
81
|
- append_after
|
84
|
-
HookScopes:
|
85
|
-
- each
|
86
|
-
- example
|
87
|
-
- context
|
88
|
-
- all
|
89
|
-
- suite
|
90
82
|
Includes:
|
91
83
|
inherit_mode:
|
92
84
|
merge:
|
@@ -98,10 +90,6 @@ RSpec:
|
|
98
90
|
- include_examples
|
99
91
|
Context:
|
100
92
|
- include_context
|
101
|
-
Runners:
|
102
|
-
- to
|
103
|
-
- to_not
|
104
|
-
- not_to
|
105
93
|
SharedGroups:
|
106
94
|
inherit_mode:
|
107
95
|
merge:
|
@@ -624,8 +612,13 @@ RSpec/MultipleSubjects:
|
|
624
612
|
RSpec/NamedSubject:
|
625
613
|
Description: Checks for explicitly referenced test subjects.
|
626
614
|
Enabled: true
|
615
|
+
EnforcedStyle: always
|
616
|
+
SupportedStyles:
|
617
|
+
- always
|
618
|
+
- named_only
|
627
619
|
IgnoreSharedExamples: true
|
628
620
|
VersionAdded: 1.5.3
|
621
|
+
VersionChanged: '2.15'
|
629
622
|
StyleGuide: https://rspec.rubystyle.guide/#use-subject
|
630
623
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject
|
631
624
|
|
@@ -55,15 +55,18 @@ module RuboCop
|
|
55
55
|
|
56
56
|
FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
|
57
57
|
|
58
|
+
RESTRICT_ON_SEND = FACTORY_CALLS
|
59
|
+
|
58
60
|
# @!method factory_call(node)
|
59
61
|
def_node_matcher :factory_call, <<-PATTERN
|
60
|
-
|
61
|
-
|
62
|
-
|
62
|
+
(send
|
63
|
+
{#factory_bot? nil?} %FACTORY_CALLS
|
64
|
+
{sym str send lvar} _*
|
65
|
+
)
|
63
66
|
PATTERN
|
64
67
|
|
65
68
|
def on_send(node)
|
66
|
-
return if
|
69
|
+
return if ambiguous_without_parentheses?(node)
|
67
70
|
|
68
71
|
factory_call(node) do
|
69
72
|
if node.parenthesized?
|
@@ -93,8 +96,10 @@ module RuboCop
|
|
93
96
|
end
|
94
97
|
end
|
95
98
|
|
96
|
-
def
|
97
|
-
node.parent&.send_type?
|
99
|
+
def ambiguous_without_parentheses?(node)
|
100
|
+
node.parent&.send_type? ||
|
101
|
+
node.parent&.pair_type? ||
|
102
|
+
node.parent&.array_type?
|
98
103
|
end
|
99
104
|
|
100
105
|
private
|
@@ -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
|
@@ -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
|
@@ -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,9 @@ module RuboCop
|
|
158
159
|
end
|
159
160
|
|
160
161
|
module Runners # :nodoc:
|
162
|
+
ALL = %i[to to_not not_to].freeze
|
161
163
|
def self.all(element)
|
162
|
-
|
164
|
+
ALL.include?(element)
|
163
165
|
end
|
164
166
|
end
|
165
167
|
|
@@ -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
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Backus
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-11-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- lib/rubocop/rspec/language.rb
|
179
179
|
- lib/rubocop/rspec/language/node_pattern.rb
|
180
180
|
- lib/rubocop/rspec/node.rb
|
181
|
+
- lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb
|
181
182
|
- lib/rubocop/rspec/version.rb
|
182
183
|
- lib/rubocop/rspec/wording.rb
|
183
184
|
homepage: https://github.com/rubocop/rubocop-rspec
|