rubocop-rspec 3.5.0 → 3.6.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 +11 -0
- data/config/default.yml +6 -0
- data/lib/rubocop/cop/rspec/change_by_zero.rb +3 -2
- data/lib/rubocop/cop/rspec/context_wording.rb +6 -1
- data/lib/rubocop/cop/rspec/described_class.rb +4 -2
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_example_group.rb +4 -4
- data/lib/rubocop/cop/rspec/expect_change.rb +21 -2
- data/lib/rubocop/cop/rspec/focus.rb +1 -1
- data/lib/rubocop/cop/rspec/hook_argument.rb +2 -2
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/include_examples.rb +39 -0
- data/lib/rubocop/cop/rspec/nested_groups.rb +2 -2
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +1 -1
- data/lib/rubocop/cop/rspec/pending.rb +1 -1
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +2 -3
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_messages.rb +1 -2
- data/lib/rubocop/cop/rspec/redundant_around.rb +1 -1
- data/lib/rubocop/cop/rspec/scattered_setup.rb +10 -2
- data/lib/rubocop/cop/rspec/variable_definition.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_name.rb +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +1 -0
- data/lib/rubocop/rspec/hook.rb +3 -1
- data/lib/rubocop/rspec/language.rb +3 -6
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e4727f136d1a399d3108fd010c76ac61f7fce57e3c89cb2d97ad121d558af44
|
4
|
+
data.tar.gz: dcc8c7f61c420d5938807dae3a610f53c6be8c657687e38542f701db2aec4ce2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 651f8b53a0b70738f9dc084df5bdf471ce65ae4d7f0c2db8cc2eb557178fd541f317bee36ae062b8109aed72b452f69eb1c965db923d5d9875c86de9ab84f23e
|
7
|
+
data.tar.gz: f189ec83b4b663df4e3aca303f2f273fded6d5529e689d7f9421f379dd46203da95236a4f649414466b0f6050b0d9e7d952df003b4b63ed45722c1764fd1a094
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 3.6.0 (2025-04-18)
|
6
|
+
|
7
|
+
- Fix false positive in `RSpec/Pending`, where it would mark the default block `it` as an offense. ([@bquorning])
|
8
|
+
- Fix issue when `Style/ContextWording` is configured with a Prefix being interpreted as a boolean, like `on`. ([@sakuro])
|
9
|
+
- Add new `RSpec/IncludeExamples` cop to enforce using `it_behaves_like` over `include_examples`. ([@dvandersluis])
|
10
|
+
- Change `RSpec/ScatteredSetup` to allow `around` hooks to be scattered. ([@ydah])
|
11
|
+
- Fix an error `RSpec/ChangeByZero` cop when without expect block. ([@lee266])
|
12
|
+
- Fix a false positive for `RSpec/DescribedClass` when `SkipBlocks` is true and numblocks are used. ([@earlopain])
|
13
|
+
|
5
14
|
## 3.5.0 (2025-02-16)
|
6
15
|
|
7
16
|
- Don't let `RSpec/PredicateMatcher` replace `respond_to?` with two arguments with the RSpec `respond_to` matcher. ([@bquorning])
|
@@ -998,6 +1007,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
998
1007
|
[@krororo]: https://github.com/krororo
|
999
1008
|
[@kuahyeow]: https://github.com/kuahyeow
|
1000
1009
|
[@lazycoder9]: https://github.com/lazycoder9
|
1010
|
+
[@lee266]: https://github.com/lee266
|
1001
1011
|
[@leoarnold]: https://github.com/leoarnold
|
1002
1012
|
[@liberatys]: https://github.com/Liberatys
|
1003
1013
|
[@lokhi]: https://github.com/lokhi
|
@@ -1038,6 +1048,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
1038
1048
|
[@rrosenblum]: https://github.com/rrosenblum
|
1039
1049
|
[@rspeicher]: https://github.com/rspeicher
|
1040
1050
|
[@rst-j]: https://github.com/RST-J
|
1051
|
+
[@sakuro]: https://github.com/sakuro
|
1041
1052
|
[@samrjenkins]: https://github.com/samrjenkins
|
1042
1053
|
[@schmijos]: https://github.com/schmijos
|
1043
1054
|
[@seanpdoyle]: https://github.com/seanpdoyle
|
data/config/default.yml
CHANGED
@@ -532,6 +532,12 @@ RSpec/ImplicitSubject:
|
|
532
532
|
VersionChanged: '2.13'
|
533
533
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject
|
534
534
|
|
535
|
+
RSpec/IncludeExamples:
|
536
|
+
Description: Checks for usage of `include_examples`.
|
537
|
+
Enabled: pending
|
538
|
+
VersionAdded: '3.6'
|
539
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IncludeExamples
|
540
|
+
|
535
541
|
RSpec/IndexedLet:
|
536
542
|
Description: Do not set up test data using indexes (e.g., `item_1`, `item_2`).
|
537
543
|
Enabled: true
|
@@ -102,6 +102,8 @@ module RuboCop
|
|
102
102
|
private
|
103
103
|
|
104
104
|
def register_offense(node, change_node)
|
105
|
+
return unless node.parent.send_type?
|
106
|
+
|
105
107
|
if compound_expectations?(node)
|
106
108
|
add_offense(node,
|
107
109
|
message: message_compound(change_node)) do |corrector|
|
@@ -116,8 +118,7 @@ module RuboCop
|
|
116
118
|
end
|
117
119
|
|
118
120
|
def compound_expectations?(node)
|
119
|
-
node.parent.
|
120
|
-
%i[and or & |].include?(node.parent.method_name)
|
121
|
+
%i[and or & |].include?(node.parent.method_name)
|
121
122
|
end
|
122
123
|
|
123
124
|
def message(change_node)
|
@@ -115,7 +115,12 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def prefixes
|
118
|
-
Array(cop_config.fetch('Prefixes', []))
|
118
|
+
Array(cop_config.fetch('Prefixes', [])).tap do |prefixes|
|
119
|
+
non_strings = prefixes.reject { |pre| pre.is_a?(String) }
|
120
|
+
unless non_strings.empty?
|
121
|
+
raise "Non-string prefixes #{non_strings.inspect} detected."
|
122
|
+
end
|
123
|
+
end
|
119
124
|
end
|
120
125
|
end
|
121
126
|
end
|
@@ -83,7 +83,7 @@ module RuboCop
|
|
83
83
|
|
84
84
|
# @!method rspec_block?(node)
|
85
85
|
def_node_matcher :rspec_block?,
|
86
|
-
'(
|
86
|
+
'(any_block (send #rspec? #ALL.all ...) ...)'
|
87
87
|
|
88
88
|
# @!method scope_changing_syntax?(node)
|
89
89
|
def_node_matcher :scope_changing_syntax?, '{def class module}'
|
@@ -153,7 +153,9 @@ module RuboCop
|
|
153
153
|
end
|
154
154
|
|
155
155
|
def skippable_block?(node)
|
156
|
-
|
156
|
+
return false unless cop_config['SkipBlocks']
|
157
|
+
|
158
|
+
node.any_block_type? && !rspec_block?(node)
|
157
159
|
end
|
158
160
|
|
159
161
|
def only_static_constants?
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
|
25
25
|
# @!method include_rspec_blocks?(node)
|
26
26
|
def_node_search :include_rspec_blocks?, <<~PATTERN
|
27
|
-
(
|
27
|
+
(any_block (send #explicit_rspec? #ExampleGroups.all ...) ...)
|
28
28
|
PATTERN
|
29
29
|
|
30
30
|
def on_module(node)
|
@@ -137,7 +137,7 @@ module RuboCop
|
|
137
137
|
PATTERN
|
138
138
|
|
139
139
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
140
|
-
return if node.each_ancestor(:
|
140
|
+
return if node.each_ancestor(:any_def).any?
|
141
141
|
return if node.each_ancestor(:block).any? { |block| example?(block) }
|
142
142
|
|
143
143
|
example_group_body(node) do |body|
|
@@ -155,7 +155,7 @@ module RuboCop
|
|
155
155
|
return true unless body
|
156
156
|
return false if conditionals_with_examples?(body)
|
157
157
|
|
158
|
-
if body.
|
158
|
+
if body.type?(:if, :case)
|
159
159
|
!examples_in_branches?(body)
|
160
160
|
else
|
161
161
|
!examples?(body)
|
@@ -163,7 +163,7 @@ module RuboCop
|
|
163
163
|
end
|
164
164
|
|
165
165
|
def conditionals_with_examples?(body)
|
166
|
-
return false unless body.
|
166
|
+
return false unless body.type?(:begin, :case)
|
167
167
|
|
168
168
|
body.each_descendant(:if, :case).any? do |condition_node|
|
169
169
|
examples_in_branches?(condition_node)
|
@@ -172,7 +172,7 @@ module RuboCop
|
|
172
172
|
|
173
173
|
def examples_in_branches?(condition_node)
|
174
174
|
return false unless condition_node
|
175
|
-
return false
|
175
|
+
return false unless condition_node.type?(:if, :case)
|
176
176
|
|
177
177
|
condition_node.branches.any? { |branch| examples?(branch) }
|
178
178
|
end
|
@@ -5,11 +5,30 @@ module RuboCop
|
|
5
5
|
module RSpec
|
6
6
|
# Checks for consistent style of change matcher.
|
7
7
|
#
|
8
|
-
# Enforces either passing
|
9
|
-
# or
|
8
|
+
# Enforces either passing a receiver and message as method arguments,
|
9
|
+
# or a block.
|
10
10
|
#
|
11
11
|
# This cop can be configured using the `EnforcedStyle` option.
|
12
12
|
#
|
13
|
+
# @safety
|
14
|
+
# Autocorrection is unsafe because `method_call` style calls the
|
15
|
+
# receiver *once* and sends the message to it before and after
|
16
|
+
# calling the `expect` block, whereas `block` style calls the
|
17
|
+
# expression *twice*, including the receiver.
|
18
|
+
#
|
19
|
+
# If your receiver is dynamic (e.g., the result of a method call) and
|
20
|
+
# you expect it to be called before and after the `expect` block,
|
21
|
+
# changing from `block` to `method_call` style may break your test.
|
22
|
+
#
|
23
|
+
# [source,ruby]
|
24
|
+
# ----
|
25
|
+
# expect { run }.to change { my_method.message }
|
26
|
+
# # `my_method` is called before and after `run`
|
27
|
+
#
|
28
|
+
# expect { run }.to change(my_method, :message)
|
29
|
+
# # `my_method` is called once, but `message` is called on it twice
|
30
|
+
# ----
|
31
|
+
#
|
13
32
|
# @example `EnforcedStyle: method_call` (default)
|
14
33
|
# # bad
|
15
34
|
# expect { run }.to change { Foo.bar }
|
@@ -67,12 +67,12 @@ module RuboCop
|
|
67
67
|
|
68
68
|
# @!method scoped_hook(node)
|
69
69
|
def_node_matcher :scoped_hook, <<~PATTERN
|
70
|
-
(
|
70
|
+
(any_block $(send _ #Hooks.all (sym ${:each :example})) ...)
|
71
71
|
PATTERN
|
72
72
|
|
73
73
|
# @!method unscoped_hook(node)
|
74
74
|
def_node_matcher :unscoped_hook, <<~PATTERN
|
75
|
-
(
|
75
|
+
(any_block $(send _ #Hooks.all) ...)
|
76
76
|
PATTERN
|
77
77
|
|
78
78
|
def on_block(node)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for usage of `include_examples`.
|
7
|
+
#
|
8
|
+
# `include_examples`, unlike `it_behaves_like`, does not create its
|
9
|
+
# own context. As such, using `subject`, `let`, `before`/`after`, etc.
|
10
|
+
# within shared examples included with `include_examples` can have
|
11
|
+
# unexpected behavior and side effects.
|
12
|
+
#
|
13
|
+
# Prefer using `it_behaves_like` instead.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# # bad
|
17
|
+
# include_examples 'examples'
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# it_behaves_like 'examples'
|
21
|
+
#
|
22
|
+
class IncludeExamples < Base
|
23
|
+
extend AutoCorrector
|
24
|
+
|
25
|
+
MSG = 'Prefer `it_behaves_like` over `include_examples`.'
|
26
|
+
|
27
|
+
RESTRICT_ON_SEND = %i[include_examples].freeze
|
28
|
+
|
29
|
+
def on_send(node)
|
30
|
+
selector = node.loc.selector
|
31
|
+
|
32
|
+
add_offense(selector) do |corrector|
|
33
|
+
corrector.replace(selector, 'it_behaves_like')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -133,8 +133,8 @@ module RuboCop
|
|
133
133
|
|
134
134
|
def count_up_nesting?(node, example_group)
|
135
135
|
example_group &&
|
136
|
-
|
137
|
-
!allowed_groups.include?(node.method_name.to_s)
|
136
|
+
node.block_type? &&
|
137
|
+
!allowed_groups.include?(node.method_name.to_s)
|
138
138
|
end
|
139
139
|
|
140
140
|
def message(nesting)
|
@@ -65,7 +65,7 @@ module RuboCop
|
|
65
65
|
# @param [RuboCop::AST::Node] node
|
66
66
|
# @return [Boolean]
|
67
67
|
def_node_matcher :regular_or_focused_example?, <<~PATTERN
|
68
|
-
(
|
68
|
+
(any_block (send nil? {#Examples.regular #Examples.focused} ...) ...)
|
69
69
|
PATTERN
|
70
70
|
|
71
71
|
# @!method includes_expectation?(node)
|
@@ -63,8 +63,7 @@ module RuboCop
|
|
63
63
|
def_node_matcher :skipped_in_example?, <<~PATTERN
|
64
64
|
{
|
65
65
|
(send nil? ${#Examples.skipped #Examples.pending})
|
66
|
-
(
|
67
|
-
(numblock (send nil? ${#Examples.skipped}) ...)
|
66
|
+
(any_block (send nil? ${#Examples.skipped}) ...)
|
68
67
|
}
|
69
68
|
PATTERN
|
70
69
|
|
@@ -75,7 +74,7 @@ module RuboCop
|
|
75
74
|
|
76
75
|
# @!method skipped_by_example_method_with_block?(node)
|
77
76
|
def_node_matcher :skipped_by_example_method_with_block?, <<~PATTERN
|
78
|
-
(
|
77
|
+
(any_block (send nil? ${#Examples.skipped #Examples.pending} ...) ...)
|
79
78
|
PATTERN
|
80
79
|
|
81
80
|
# @!method metadata_without_reason?(node)
|
@@ -148,8 +148,7 @@ module RuboCop
|
|
148
148
|
end
|
149
149
|
|
150
150
|
def heredoc_or_splat?(node)
|
151
|
-
(
|
152
|
-
node.splat_type?
|
151
|
+
(node.type?(:str, :dstr) && node.heredoc?) || node.splat_type?
|
153
152
|
end
|
154
153
|
|
155
154
|
def requires_quotes?(value)
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
41
41
|
|
42
42
|
# @!method match_redundant_around_hook_block?(node)
|
43
43
|
def_node_matcher :match_redundant_around_hook_block?, <<~PATTERN
|
44
|
-
(
|
44
|
+
(any_block (send _ :around ...) ... (send _ :run))
|
45
45
|
PATTERN
|
46
46
|
|
47
47
|
# @!method match_redundant_around_hook_send?(node)
|
@@ -5,7 +5,9 @@ module RuboCop
|
|
5
5
|
module RSpec
|
6
6
|
# Checks for setup scattered across multiple hooks in an example group.
|
7
7
|
#
|
8
|
-
# Unify `before
|
8
|
+
# Unify `before` and `after` hooks when possible.
|
9
|
+
# However, `around` hooks are allowed to be defined multiple times,
|
10
|
+
# as unifying them would typically make the code harder to read.
|
9
11
|
#
|
10
12
|
# @example
|
11
13
|
# # bad
|
@@ -22,6 +24,12 @@ module RuboCop
|
|
22
24
|
# end
|
23
25
|
# end
|
24
26
|
#
|
27
|
+
# # good
|
28
|
+
# describe Foo do
|
29
|
+
# around { |example| before1; example.call; after1 }
|
30
|
+
# around { |example| before2; example.call; after2 }
|
31
|
+
# end
|
32
|
+
#
|
25
33
|
class ScatteredSetup < Base
|
26
34
|
include FinalEndLocation
|
27
35
|
include RangeHelp
|
@@ -48,7 +56,7 @@ module RuboCop
|
|
48
56
|
def repeated_hooks(node)
|
49
57
|
hooks = RuboCop::RSpec::ExampleGroup.new(node)
|
50
58
|
.hooks
|
51
|
-
.select
|
59
|
+
.select { |hook| hook.knowable_scope? && hook.name != :around }
|
52
60
|
.group_by { |hook| [hook.name, hook.scope, hook.metadata] }
|
53
61
|
.values
|
54
62
|
.reject(&:one?)
|
@@ -50,7 +50,7 @@ module RuboCop
|
|
50
50
|
return unless inside_example_group?(node)
|
51
51
|
|
52
52
|
variable_definition?(node) do |variable|
|
53
|
-
return if variable.
|
53
|
+
return if variable.type?(:dstr, :dsym)
|
54
54
|
return if matches_allowed_pattern?(variable.value)
|
55
55
|
|
56
56
|
check_name(node, variable.value, variable.source_range)
|
@@ -48,6 +48,7 @@ require_relative 'rspec/identical_equality_assertion'
|
|
48
48
|
require_relative 'rspec/implicit_block_expectation'
|
49
49
|
require_relative 'rspec/implicit_expect'
|
50
50
|
require_relative 'rspec/implicit_subject'
|
51
|
+
require_relative 'rspec/include_examples'
|
51
52
|
require_relative 'rspec/indexed_let'
|
52
53
|
require_relative 'rspec/instance_spy'
|
53
54
|
require_relative 'rspec/instance_variable'
|
data/lib/rubocop/rspec/hook.rb
CHANGED
@@ -26,7 +26,7 @@ module RuboCop
|
|
26
26
|
|
27
27
|
# @!method example_group?(node)
|
28
28
|
def_node_matcher :example_group?, <<~PATTERN
|
29
|
-
(
|
29
|
+
(any_block (send #rspec? #ExampleGroups.all ...) ...)
|
30
30
|
PATTERN
|
31
31
|
|
32
32
|
# @!method shared_group?(node)
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
35
35
|
|
36
36
|
# @!method spec_group?(node)
|
37
37
|
def_node_matcher :spec_group?, <<~PATTERN
|
38
|
-
(
|
38
|
+
(any_block (send #rspec?
|
39
39
|
{#SharedGroups.all #ExampleGroups.all}
|
40
40
|
...) ...)
|
41
41
|
PATTERN
|
@@ -50,10 +50,7 @@ module RuboCop
|
|
50
50
|
|
51
51
|
# @!method hook?(node)
|
52
52
|
def_node_matcher :hook?, <<~PATTERN
|
53
|
-
|
54
|
-
(numblock (send nil? #Hooks.all ...) ...)
|
55
|
-
(block (send nil? #Hooks.all ...) ...)
|
56
|
-
}
|
53
|
+
(any_block (send nil? #Hooks.all ...) ...)
|
57
54
|
PATTERN
|
58
55
|
|
59
56
|
# @!method let?(node)
|
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Backus
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
- Nils Gemeinhardt
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: lint_roller
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/rubocop/cop/rspec/implicit_block_expectation.rb
|
115
115
|
- lib/rubocop/cop/rspec/implicit_expect.rb
|
116
116
|
- lib/rubocop/cop/rspec/implicit_subject.rb
|
117
|
+
- lib/rubocop/cop/rspec/include_examples.rb
|
117
118
|
- lib/rubocop/cop/rspec/indexed_let.rb
|
118
119
|
- lib/rubocop/cop/rspec/instance_spy.rb
|
119
120
|
- lib/rubocop/cop/rspec/instance_variable.rb
|
@@ -226,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
226
227
|
- !ruby/object:Gem::Version
|
227
228
|
version: '0'
|
228
229
|
requirements: []
|
229
|
-
rubygems_version: 3.6.
|
230
|
+
rubygems_version: 3.6.7
|
230
231
|
specification_version: 4
|
231
232
|
summary: Code style checking for RSpec files
|
232
233
|
test_files: []
|