rubocop-rspec 3.6.0 → 3.7.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 +12 -0
- data/config/default.yml +10 -1
- data/lib/rubocop/cop/rspec/described_class.rb +21 -10
- data/lib/rubocop/cop/rspec/dialect.rb +1 -0
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -1
- data/lib/rubocop/cop/rspec/include_examples.rb +51 -0
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +32 -10
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +7 -0
- data/lib/rubocop/cop/rspec/receive_messages.rb +1 -1
- data/lib/rubocop/rspec/language.rb +10 -4
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 645fbfddd891af3477e31993bc8da92fc57300cbcfcd8274ee0f68cfbbe97983
|
4
|
+
data.tar.gz: 6a97e91acb933ecbe09691c090efbff715ca12adcaef7027e8d324411ec0d78d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca10e4b0b7e285136c60aa0035a018407263968fcced15155999ef5e2b6ac4edac45bcbd6c82dd355616a40ef110f9191cc986d5a8922aaab42c8118bff55c89
|
7
|
+
data.tar.gz: 7a22acf8143f309128504884a1634e23504b40821aabf14d9b20392c6c11ce7a34ad3ab48945e1b023594a794677bdf6526e7236f705fd331ab244a746375453
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 3.7.0 (2025-09-01)
|
6
|
+
|
7
|
+
- Mark `RSpec/IncludeExamples` as `SafeAutoCorrect: false`. ([@yujideveloper])
|
8
|
+
- Fix a false positive for `RSpec/LeakyConstantDeclaration` when defining constants in explicit namespaces. ([@naveg])
|
9
|
+
- Add support for error matchers (`raise_exception` and `raise_error`) to `RSpec/Dialect`. ([@lovro-bikic])
|
10
|
+
- Don't register offenses for `RSpec/DescribedClass` within `Data.define` blocks. ([@lovro-bikic])
|
11
|
+
- Add autocorrection support for `RSpec/IteratedExpectation` for single expectations. ([@lovro-bikic])
|
12
|
+
- Exclude all cops from inspecting factorybot files, except if explicitly included. ([@Mth0158])
|
13
|
+
- Fix a false positive for `RSpec/ExcessiveDocstringSpacing` when receivers are not RSpec methods. ([@ydah])
|
14
|
+
|
5
15
|
## 3.6.0 (2025-04-18)
|
6
16
|
|
7
17
|
- Fix false positive in `RSpec/Pending`, where it would mark the default block `it` as an offense. ([@bquorning])
|
@@ -1021,6 +1031,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
1021
1031
|
[@mlarraz]: https://github.com/mlarraz
|
1022
1032
|
[@mockdeep]: https://github.com/mockdeep
|
1023
1033
|
[@mothonmars]: https://github.com/MothOnMars
|
1034
|
+
[@mth0158]: https://github.com/Mth0158
|
1024
1035
|
[@mvz]: https://github.com/mvz
|
1025
1036
|
[@naveg]: https://github.com/naveg
|
1026
1037
|
[@nc-holodakg]: https://github.com/nc-holodakg
|
@@ -1073,5 +1084,6 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
1073
1084
|
[@ydah]: https://github.com/ydah
|
1074
1085
|
[@yevhene]: https://github.com/yevhene
|
1075
1086
|
[@ypresto]: https://github.com/ypresto
|
1087
|
+
[@yujideveloper]: https://github.com/yujideveloper
|
1076
1088
|
[@zdennis]: https://github.com/zdennis
|
1077
1089
|
[@zverok]: https://github.com/zverok
|
data/config/default.yml
CHANGED
@@ -6,6 +6,10 @@ RSpec:
|
|
6
6
|
Include:
|
7
7
|
- "**/*_spec.rb"
|
8
8
|
- "**/spec/**/*"
|
9
|
+
Exclude:
|
10
|
+
- "**/spec/factories.rb"
|
11
|
+
- "**/spec/factories/**/*.rb"
|
12
|
+
- "**/features/support/factories/**/*.rb"
|
9
13
|
Language:
|
10
14
|
inherit_mode:
|
11
15
|
merge:
|
@@ -79,6 +83,9 @@ RSpec:
|
|
79
83
|
- prepend_after
|
80
84
|
- after
|
81
85
|
- append_after
|
86
|
+
ErrorMatchers:
|
87
|
+
- raise_error
|
88
|
+
- raise_exception
|
82
89
|
Includes:
|
83
90
|
inherit_mode:
|
84
91
|
merge:
|
@@ -535,7 +542,9 @@ RSpec/ImplicitSubject:
|
|
535
542
|
RSpec/IncludeExamples:
|
536
543
|
Description: Checks for usage of `include_examples`.
|
537
544
|
Enabled: pending
|
545
|
+
SafeAutoCorrect: false
|
538
546
|
VersionAdded: '3.6'
|
547
|
+
VersionChanged: '3.7'
|
539
548
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IncludeExamples
|
540
549
|
|
541
550
|
RSpec/IndexedLet:
|
@@ -782,7 +791,7 @@ RSpec/ReceiveCounts:
|
|
782
791
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts
|
783
792
|
|
784
793
|
RSpec/ReceiveMessages:
|
785
|
-
Description:
|
794
|
+
Description: Prefer `receive_messages` over multiple `receive`s on the same object.
|
786
795
|
Enabled: true
|
787
796
|
SafeAutoCorrect: false
|
788
797
|
VersionAdded: '2.23'
|
@@ -13,6 +13,20 @@ module RuboCop
|
|
13
13
|
# `OnlyStaticConstants` is only relevant when `EnforcedStyle` is
|
14
14
|
# `described_class`.
|
15
15
|
#
|
16
|
+
# There's a known caveat with rspec-rails's `controller` helper that
|
17
|
+
# runs its block in a different context, and `described_class` is not
|
18
|
+
# available to it. `SkipBlocks` option excludes detection in all
|
19
|
+
# non-RSpec related blocks.
|
20
|
+
#
|
21
|
+
# To narrow down this setting to only a specific directory, it is
|
22
|
+
# possible to use an overriding configuration file local to that
|
23
|
+
# directory.
|
24
|
+
#
|
25
|
+
# @safety
|
26
|
+
# Autocorrection is unsafe when `SkipBlocks: false` because
|
27
|
+
# `described_class` might not be available within the block (for
|
28
|
+
# example, in rspec-rails's `controller` helper).
|
29
|
+
#
|
16
30
|
# @example `EnforcedStyle: described_class` (default)
|
17
31
|
# # bad
|
18
32
|
# describe MyClass do
|
@@ -47,15 +61,6 @@ module RuboCop
|
|
47
61
|
# subject { MyClass.do_something }
|
48
62
|
# end
|
49
63
|
#
|
50
|
-
# There's a known caveat with rspec-rails's `controller` helper that
|
51
|
-
# runs its block in a different context, and `described_class` is not
|
52
|
-
# available to it. `SkipBlocks` option excludes detection in all
|
53
|
-
# non-RSpec related blocks.
|
54
|
-
#
|
55
|
-
# To narrow down this setting to only a specific directory, it is
|
56
|
-
# possible to use an overriding configuration file local to that
|
57
|
-
# directory.
|
58
|
-
#
|
59
64
|
# @example `SkipBlocks: true`
|
60
65
|
# # spec/controllers/.rubocop.yml
|
61
66
|
# # RSpec/DescribedClass:
|
@@ -78,7 +83,13 @@ module RuboCop
|
|
78
83
|
|
79
84
|
# @!method common_instance_exec_closure?(node)
|
80
85
|
def_node_matcher :common_instance_exec_closure?, <<~PATTERN
|
81
|
-
(block
|
86
|
+
(block
|
87
|
+
{
|
88
|
+
(send (const nil? {:Class :Module :Struct}) :new ...)
|
89
|
+
(send (const nil? :Data) :define ...)
|
90
|
+
}
|
91
|
+
...
|
92
|
+
)
|
82
93
|
PATTERN
|
83
94
|
|
84
95
|
# @!method rspec_block?(node)
|
@@ -30,7 +30,7 @@ module RuboCop
|
|
30
30
|
|
31
31
|
# @!method example_description(node)
|
32
32
|
def_node_matcher :example_description, <<~PATTERN
|
33
|
-
(send
|
33
|
+
(send #rspec? {#Examples.all #ExampleGroups.all} ${
|
34
34
|
$str
|
35
35
|
$(dstr ({str dstr `sym} ...) ...)
|
36
36
|
} ...)
|
@@ -12,6 +12,57 @@ module RuboCop
|
|
12
12
|
#
|
13
13
|
# Prefer using `it_behaves_like` instead.
|
14
14
|
#
|
15
|
+
# @safety
|
16
|
+
# `include_examples` and `it_behaves_like` have different scoping
|
17
|
+
# behaviors.
|
18
|
+
# Changing `include_examples` to `it_behaves_like` creates a new
|
19
|
+
# context, altering setup dependencies, which can lead to unexpected
|
20
|
+
# test failures.
|
21
|
+
# Specifically, the scope of hooks (`before`, `after`, `around`)
|
22
|
+
# changes, which may prevent expected setup from being inherited
|
23
|
+
# correctly.
|
24
|
+
#
|
25
|
+
# Additionally, `let` and `subject` are affected by scoping rules.
|
26
|
+
# When `include_examples` is used, `let` and `subject` defined within
|
27
|
+
# `shared_examples` are evaluated in the caller's context, allowing
|
28
|
+
# access to their values.
|
29
|
+
# In contrast, `it_behaves_like` creates a new context, preventing
|
30
|
+
# access to `let` or `subject` values from the caller's context.
|
31
|
+
#
|
32
|
+
# [source,ruby]
|
33
|
+
# ----
|
34
|
+
# shared_examples "mock behavior" do
|
35
|
+
# before do
|
36
|
+
# allow(service).to receive(:call).and_return("mocked response")
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# it "returns mocked response" do
|
40
|
+
# expect(service.call).to eq "mocked response"
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# context "working example with include_examples" do
|
45
|
+
# let(:service) { double(:service) }
|
46
|
+
#
|
47
|
+
# include_examples "mock behavior"
|
48
|
+
#
|
49
|
+
# it "uses the mocked service" do
|
50
|
+
# expect(service.call).to eq "mocked response" # Passes
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# context "broken example with it_behaves_like" do
|
55
|
+
# let(:service) { double(:service) }
|
56
|
+
#
|
57
|
+
# it_behaves_like "mock behavior"
|
58
|
+
#
|
59
|
+
# it "unexpectedly does not use the mocked service" do
|
60
|
+
# # Fails because `it_behaves_like` does not apply the mock setup
|
61
|
+
# expect(service.call).to eq "mocked response"
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
# ----
|
65
|
+
#
|
15
66
|
# @example
|
16
67
|
# # bad
|
17
68
|
# include_examples 'examples'
|
@@ -17,6 +17,8 @@ module RuboCop
|
|
17
17
|
# end
|
18
18
|
#
|
19
19
|
class IteratedExpectation < Base
|
20
|
+
extend AutoCorrector
|
21
|
+
|
20
22
|
MSG = 'Prefer using the `all` matcher instead ' \
|
21
23
|
'of iterating over an array.'
|
22
24
|
|
@@ -25,14 +27,14 @@ module RuboCop
|
|
25
27
|
(block
|
26
28
|
(send ... :each)
|
27
29
|
(args (arg $_))
|
28
|
-
|
30
|
+
(...)
|
29
31
|
)
|
30
32
|
PATTERN
|
31
33
|
|
32
34
|
# @!method each_numblock?(node)
|
33
35
|
def_node_matcher :each_numblock?, <<~PATTERN
|
34
36
|
(numblock
|
35
|
-
(send ... :each) _
|
37
|
+
(send ... :each) _ (...)
|
36
38
|
)
|
37
39
|
PATTERN
|
38
40
|
|
@@ -42,23 +44,43 @@ module RuboCop
|
|
42
44
|
PATTERN
|
43
45
|
|
44
46
|
def on_block(node)
|
45
|
-
each?(node) do |arg
|
46
|
-
|
47
|
-
add_offense(node.send_node)
|
48
|
-
end
|
47
|
+
each?(node) do |arg|
|
48
|
+
check_offense(node, arg)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
52
|
def on_numblock(node)
|
53
|
-
each_numblock?(node) do
|
54
|
-
|
55
|
-
add_offense(node.send_node)
|
56
|
-
end
|
53
|
+
each_numblock?(node) do
|
54
|
+
check_offense(node, :_1)
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
60
58
|
private
|
61
59
|
|
60
|
+
def check_offense(node, argument)
|
61
|
+
if single_expectation?(node.body, argument)
|
62
|
+
add_offense(node.send_node) do |corrector|
|
63
|
+
next unless node.body.arguments.one?
|
64
|
+
next if uses_argument_in_matcher?(node, argument)
|
65
|
+
|
66
|
+
corrector.replace(node, single_expectation_replacement(node))
|
67
|
+
end
|
68
|
+
elsif only_expectations?(node.body, argument)
|
69
|
+
add_offense(node.send_node)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def single_expectation_replacement(node)
|
74
|
+
collection = node.receiver.source
|
75
|
+
matcher = node.body.first_argument.source
|
76
|
+
|
77
|
+
"expect(#{collection}).to all(#{matcher})"
|
78
|
+
end
|
79
|
+
|
80
|
+
def uses_argument_in_matcher?(node, argument)
|
81
|
+
node.body.first_argument.each_descendant.any?(s(:lvar, argument))
|
82
|
+
end
|
83
|
+
|
62
84
|
def single_expectation?(body, arg)
|
63
85
|
expectation?(body, arg)
|
64
86
|
end
|
@@ -100,18 +100,21 @@ module RuboCop
|
|
100
100
|
|
101
101
|
def on_casgn(node)
|
102
102
|
return unless inside_describe_block?(node)
|
103
|
+
return if explicit_namespace?(node.namespace)
|
103
104
|
|
104
105
|
add_offense(node, message: MSG_CONST)
|
105
106
|
end
|
106
107
|
|
107
108
|
def on_class(node)
|
108
109
|
return unless inside_describe_block?(node)
|
110
|
+
return if explicit_namespace?(node.identifier.namespace)
|
109
111
|
|
110
112
|
add_offense(node, message: MSG_CLASS)
|
111
113
|
end
|
112
114
|
|
113
115
|
def on_module(node)
|
114
116
|
return unless inside_describe_block?(node)
|
117
|
+
return if explicit_namespace?(node.identifier.namespace)
|
115
118
|
|
116
119
|
add_offense(node, message: MSG_MODULE)
|
117
120
|
end
|
@@ -121,6 +124,10 @@ module RuboCop
|
|
121
124
|
def inside_describe_block?(node)
|
122
125
|
node.each_ancestor(:block).any? { |ancestor| spec_group?(ancestor) }
|
123
126
|
end
|
127
|
+
|
128
|
+
def explicit_namespace?(namespace)
|
129
|
+
!namespace.nil?
|
130
|
+
end
|
124
131
|
end
|
125
132
|
end
|
126
133
|
end
|
@@ -72,6 +72,12 @@ module RuboCop
|
|
72
72
|
# @!method subject?(node)
|
73
73
|
def_node_matcher :subject?, '(block (send nil? #Subjects.all ...) ...)'
|
74
74
|
|
75
|
+
module ErrorMatchers # :nodoc:
|
76
|
+
def self.all(element)
|
77
|
+
Language.config['ErrorMatchers'].include?(element.to_s)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
75
81
|
module ExampleGroups # :nodoc:
|
76
82
|
class << self
|
77
83
|
def all(element)
|
@@ -200,14 +206,14 @@ module RuboCop
|
|
200
206
|
# This is used in Dialect and DescribeClass cops to detect RSpec blocks.
|
201
207
|
module ALL # :nodoc:
|
202
208
|
def self.all(element)
|
203
|
-
[ExampleGroups, Examples, Expectations, Helpers, Hooks,
|
204
|
-
Runners, SharedGroups, Subjects]
|
209
|
+
[ErrorMatchers, ExampleGroups, Examples, Expectations, Helpers, Hooks,
|
210
|
+
Includes, Runners, SharedGroups, Subjects]
|
205
211
|
.find { |concept| concept.all(element) }
|
206
212
|
end
|
207
213
|
end
|
208
214
|
|
209
|
-
private_constant :ExampleGroups, :Examples, :Expectations,
|
210
|
-
:Includes, :Runners, :SharedGroups, :ALL
|
215
|
+
private_constant :ErrorMatchers, :ExampleGroups, :Examples, :Expectations,
|
216
|
+
:Hooks, :Includes, :Runners, :SharedGroups, :ALL
|
211
217
|
end
|
212
218
|
end
|
213
219
|
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: 3.
|
4
|
+
version: 3.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Backus
|
@@ -227,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
227
227
|
- !ruby/object:Gem::Version
|
228
228
|
version: '0'
|
229
229
|
requirements: []
|
230
|
-
rubygems_version: 3.6.
|
230
|
+
rubygems_version: 3.6.9
|
231
231
|
specification_version: 4
|
232
232
|
summary: Code style checking for RSpec files
|
233
233
|
test_files: []
|