rubocop-rspec 2.10.0 → 2.11.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 +9 -0
- data/config/default.yml +17 -3
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +1 -1
- data/lib/rubocop/cop/rspec/change_by_zero.rb +88 -0
- data/lib/rubocop/cop/rspec/described_class.rb +12 -19
- data/lib/rubocop/cop/rspec/dialect.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_change.rb +4 -4
- data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +1 -1
- data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/yield.rb +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +1 -0
- data/lib/rubocop/rspec/config_formatter.rb +3 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b1c8f65ec3429d357c99302f307f318750117e2329719e4cffc60123546a356
|
4
|
+
data.tar.gz: 178b52063271fe727162e196b6a364254e86a7343233ee8d15ad2d27f812367d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdc010e5813ab0d100c50da5686ce10dfff440fb279c01a0f7c0a99f5066202cea53789cbee6d3792b75cc22ce1574e6f06f216822a7ebb960e39f8ad8994139
|
7
|
+
data.tar.gz: 055a453f761b8d6ebda211002f2d0265deb4cdc2f8b5567d71cf28d25bcba7d34a1be7f88bd3e7768e29671bb278aa9af4bb6bc910e42008ee083c4c33525cc4
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.11.0 (2022-05-18)
|
6
|
+
|
7
|
+
* Drop Ruby 2.5 support. ([@ydah][])
|
8
|
+
* Add new `RSpec/ChangeByZero` cop. ([@ydah][])
|
9
|
+
* Improve `RSpec/ExpectChange` to detect namespaced and top-level constants. ([@M-Yamashita01][])
|
10
|
+
* Introduce an amendment to `Metrics/BlockLength` to exclude spec files. ([@luke-hill][])
|
11
|
+
|
5
12
|
## 2.10.0 (2022-04-19)
|
6
13
|
|
7
14
|
* Fix a false positive for `RSpec/EmptyExampleGroup` when expectations in case statement. ([@ydah][])
|
@@ -681,3 +688,5 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
681
688
|
[@oshiro3]: https://github.com/oshiro3
|
682
689
|
[@ydah]: https://github.com/ydah
|
683
690
|
[@t3h2mas]: https://github.com/t3h2mas
|
691
|
+
[@M-Yamashita01]: https://github.com/M-Yamashita01
|
692
|
+
[@luke-hill]: https://github.com/luke-hill
|
data/config/default.yml
CHANGED
@@ -110,6 +110,14 @@ RSpec:
|
|
110
110
|
- subject
|
111
111
|
- subject!
|
112
112
|
|
113
|
+
Metrics/BlockLength:
|
114
|
+
inherit_mode:
|
115
|
+
merge:
|
116
|
+
- Exclude
|
117
|
+
Exclude:
|
118
|
+
- "**/*_spec.rb"
|
119
|
+
- "**/spec/**/*"
|
120
|
+
|
113
121
|
RSpec/AlignLeftLetBrace:
|
114
122
|
Description: Checks that left braces for adjacent single line lets are aligned.
|
115
123
|
Enabled: false
|
@@ -176,6 +184,12 @@ RSpec/BeforeAfterAll:
|
|
176
184
|
StyleGuide: https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope
|
177
185
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
|
178
186
|
|
187
|
+
RSpec/ChangeByZero:
|
188
|
+
Description: Prefer negated matchers over `to change.by(0)`.
|
189
|
+
Enabled: pending
|
190
|
+
VersionAdded: 2.11.0
|
191
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ChangeByZero
|
192
|
+
|
179
193
|
RSpec/ContextMethod:
|
180
194
|
Description: "`context` should not be used for specifying methods."
|
181
195
|
Enabled: true
|
@@ -256,7 +270,7 @@ RSpec/DescribedClassModuleWrapping:
|
|
256
270
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping
|
257
271
|
|
258
272
|
RSpec/Dialect:
|
259
|
-
Description:
|
273
|
+
Description: Enforces custom RSpec dialects.
|
260
274
|
Enabled: false
|
261
275
|
PreferredMethods: {}
|
262
276
|
VersionAdded: '1.33'
|
@@ -787,13 +801,13 @@ RSpec/VerifiedDoubles:
|
|
787
801
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles
|
788
802
|
|
789
803
|
RSpec/VoidExpect:
|
790
|
-
Description:
|
804
|
+
Description: Checks void `expect()`.
|
791
805
|
Enabled: true
|
792
806
|
VersionAdded: '1.16'
|
793
807
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect
|
794
808
|
|
795
809
|
RSpec/Yield:
|
796
|
-
Description:
|
810
|
+
Description: Checks for calling a block within a stub.
|
797
811
|
Enabled: true
|
798
812
|
VersionAdded: '1.32'
|
799
813
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
|
47
47
|
MSG = 'Use `%<replacement>s` instead of `%<method>s`.'
|
48
48
|
|
49
|
-
# https://
|
49
|
+
# https://github.com/teamcapybara/capybara/blob/e283c1aeaa72441f5403963577e16333bf111a81/lib/capybara/rspec/features.rb#L31-L36
|
50
50
|
MAP = {
|
51
51
|
background: :before,
|
52
52
|
scenario: :it,
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Prefer negated matchers over `to change.by(0)`.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# expect { run }.to change(Foo, :bar).by(0)
|
11
|
+
# expect { run }.to change { Foo.bar }.by(0)
|
12
|
+
# expect { run }
|
13
|
+
# .to change(Foo, :bar).by(0)
|
14
|
+
# .and change(Foo, :baz).by(0)
|
15
|
+
# expect { run }
|
16
|
+
# .to change { Foo.bar }.by(0)
|
17
|
+
# .and change { Foo.baz }.by(0)
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# expect { run }.not_to change(Foo, :bar)
|
21
|
+
# expect { run }.not_to change { Foo.bar }
|
22
|
+
# expect { run }
|
23
|
+
# .to not_change(Foo, :bar)
|
24
|
+
# .and not_change(Foo, :baz)
|
25
|
+
# expect { run }
|
26
|
+
# .to not_change { Foo.bar }
|
27
|
+
# .and not_change { Foo.baz }
|
28
|
+
#
|
29
|
+
class ChangeByZero < Base
|
30
|
+
extend AutoCorrector
|
31
|
+
MSG = 'Prefer `not_to change` over `to change.by(0)`.'
|
32
|
+
MSG_COMPOUND = 'Prefer negated matchers with compound expectations ' \
|
33
|
+
'over `change.by(0)`.'
|
34
|
+
RESTRICT_ON_SEND = %i[change].freeze
|
35
|
+
|
36
|
+
# @!method expect_change_with_arguments(node)
|
37
|
+
def_node_matcher :expect_change_with_arguments, <<-PATTERN
|
38
|
+
(send
|
39
|
+
(send nil? :change ...) :by
|
40
|
+
(int 0))
|
41
|
+
PATTERN
|
42
|
+
|
43
|
+
# @!method expect_change_with_block(node)
|
44
|
+
def_node_matcher :expect_change_with_block, <<-PATTERN
|
45
|
+
(send
|
46
|
+
(block
|
47
|
+
(send nil? :change)
|
48
|
+
(args)
|
49
|
+
(send (...) $_)) :by
|
50
|
+
(int 0))
|
51
|
+
PATTERN
|
52
|
+
|
53
|
+
def on_send(node)
|
54
|
+
expect_change_with_arguments(node.parent) do
|
55
|
+
check_offence(node.parent)
|
56
|
+
end
|
57
|
+
|
58
|
+
expect_change_with_block(node.parent.parent) do
|
59
|
+
check_offence(node.parent.parent)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def check_offence(node)
|
66
|
+
expression = node.loc.expression
|
67
|
+
if compound_expectations?(node)
|
68
|
+
add_offense(expression, message: MSG_COMPOUND)
|
69
|
+
else
|
70
|
+
add_offense(expression) do |corrector|
|
71
|
+
autocorrect(corrector, node)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def compound_expectations?(node)
|
77
|
+
%i[and or].include?(node.parent.method_name)
|
78
|
+
end
|
79
|
+
|
80
|
+
def autocorrect(corrector, node)
|
81
|
+
corrector.replace(node.parent.loc.selector, 'not_to')
|
82
|
+
range = node.loc.dot.with(end_pos: node.loc.expression.end_pos)
|
83
|
+
corrector.remove(range)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -78,9 +78,8 @@ module RuboCop
|
|
78
78
|
PATTERN
|
79
79
|
|
80
80
|
# @!method contains_described_class?(node)
|
81
|
-
def_node_search :contains_described_class?,
|
82
|
-
|
83
|
-
PATTERN
|
81
|
+
def_node_search :contains_described_class?,
|
82
|
+
'(send nil? :described_class)'
|
84
83
|
|
85
84
|
def on_block(node)
|
86
85
|
# In case the explicit style is used, we need to remember what's
|
@@ -129,17 +128,13 @@ module RuboCop
|
|
129
128
|
end
|
130
129
|
|
131
130
|
def scope_change?(node)
|
132
|
-
scope_changing_syntax?(node)
|
131
|
+
scope_changing_syntax?(node) ||
|
133
132
|
common_instance_exec_closure?(node) ||
|
134
133
|
skippable_block?(node)
|
135
134
|
end
|
136
135
|
|
137
136
|
def skippable_block?(node)
|
138
|
-
node.block_type? && !rspec_block?(node) &&
|
139
|
-
end
|
140
|
-
|
141
|
-
def skip_blocks?
|
142
|
-
cop_config['SkipBlocks']
|
137
|
+
node.block_type? && !rspec_block?(node) && cop_config['SkipBlocks']
|
143
138
|
end
|
144
139
|
|
145
140
|
def offensive?(node)
|
@@ -152,6 +147,7 @@ module RuboCop
|
|
152
147
|
|
153
148
|
def offensive_described_class?(node)
|
154
149
|
return unless node.const_type?
|
150
|
+
|
155
151
|
# E.g. `described_class::CONSTANT`
|
156
152
|
return if contains_described_class?(node)
|
157
153
|
|
@@ -172,14 +168,13 @@ module RuboCop
|
|
172
168
|
# @return [Array<Symbol>]
|
173
169
|
# @example
|
174
170
|
# # nil represents base constant
|
175
|
-
# collapse_namespace([], :C)
|
176
|
-
# collapse_namespace([:A, :B], [:C) # => [:A, :B, :C]
|
177
|
-
# collapse_namespace([:A, :B], [:B, :C) # => [:A, :B, :C]
|
178
|
-
# collapse_namespace([:A, :B], [nil, :C) # => [nil, :C]
|
179
|
-
# collapse_namespace([:A, :B], [nil, :B, :C) # => [nil, :B, :C]
|
171
|
+
# collapse_namespace([], [:C]) # => [:C]
|
172
|
+
# collapse_namespace([:A, :B], [:C]) # => [:A, :B, :C]
|
173
|
+
# collapse_namespace([:A, :B], [:B, :C]) # => [:A, :B, :C]
|
174
|
+
# collapse_namespace([:A, :B], [nil, :C]) # => [nil, :C]
|
175
|
+
# collapse_namespace([:A, :B], [nil, :B, :C]) # => [nil, :B, :C]
|
180
176
|
def collapse_namespace(namespace, const)
|
181
|
-
return const if namespace.empty?
|
182
|
-
return const if const.first.nil?
|
177
|
+
return const if namespace.empty? || const.first.nil?
|
183
178
|
|
184
179
|
start = [0, (namespace.length - const.length)].max
|
185
180
|
max = namespace.length
|
@@ -196,9 +191,7 @@ module RuboCop
|
|
196
191
|
# const_name(s(:const, s(:const, nil, :M), :C)) # => [:M, :C]
|
197
192
|
# const_name(s(:const, s(:cbase), :C)) # => [nil, :C]
|
198
193
|
def const_name(node)
|
199
|
-
# rubocop:disable InternalAffairs/NodeDestructuring
|
200
|
-
namespace, name = *node
|
201
|
-
# rubocop:enable InternalAffairs/NodeDestructuring
|
194
|
+
namespace, name = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
202
195
|
if !namespace
|
203
196
|
[name]
|
204
197
|
elsif namespace.const_type?
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
39
39
|
|
40
40
|
# @!method expect_change_with_arguments(node)
|
41
41
|
def_node_matcher :expect_change_with_arguments, <<-PATTERN
|
42
|
-
(send nil? :change $_ (sym $_))
|
42
|
+
(send nil? :change $_ ({sym str} $_))
|
43
43
|
PATTERN
|
44
44
|
|
45
45
|
# @!method expect_change_with_block(node)
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
(block
|
48
48
|
(send nil? :change)
|
49
49
|
(args)
|
50
|
-
(send
|
50
|
+
(send $_ $_)
|
51
51
|
)
|
52
52
|
PATTERN
|
53
53
|
|
@@ -67,9 +67,9 @@ module RuboCop
|
|
67
67
|
return unless style == :method_call
|
68
68
|
|
69
69
|
expect_change_with_block(node) do |receiver, message|
|
70
|
-
msg = format(MSG_BLOCK, obj: receiver, attr: message)
|
70
|
+
msg = format(MSG_BLOCK, obj: receiver.source, attr: message)
|
71
71
|
add_offense(node, message: msg) do |corrector|
|
72
|
-
replacement = "change(#{receiver}, :#{message})"
|
72
|
+
replacement = "change(#{receiver.source}, :#{message})"
|
73
73
|
corrector.replace(node, replacement)
|
74
74
|
end
|
75
75
|
end
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
# rubocop:disable InternalAffairs/NodeDestructuring
|
25
25
|
variable_name, _rhs = *node
|
26
26
|
# rubocop:enable InternalAffairs/NodeDestructuring
|
27
|
-
name = variable_name[1
|
27
|
+
name = variable_name[1..]
|
28
28
|
return unless name.eql?('stdout') || name.eql?('stderr')
|
29
29
|
|
30
30
|
add_offense(node.loc.name, message: format(MSG, name: name))
|
@@ -25,6 +25,7 @@ require_relative 'rspec/be_eq'
|
|
25
25
|
require_relative 'rspec/be_eql'
|
26
26
|
require_relative 'rspec/be_nil'
|
27
27
|
require_relative 'rspec/before_after_all'
|
28
|
+
require_relative 'rspec/change_by_zero'
|
28
29
|
require_relative 'rspec/context_method'
|
29
30
|
require_relative 'rspec/context_wording'
|
30
31
|
require_relative 'rspec/describe_class'
|
@@ -8,6 +8,7 @@ module RuboCop
|
|
8
8
|
class ConfigFormatter
|
9
9
|
EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
|
10
10
|
SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails)
|
11
|
+
AMENDMENTS = %(Metrics/BlockLength)
|
11
12
|
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/'
|
12
13
|
|
13
14
|
def initialize(config, descriptions)
|
@@ -18,6 +19,7 @@ module RuboCop
|
|
18
19
|
def dump
|
19
20
|
YAML.dump(unified_config)
|
20
21
|
.gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
|
22
|
+
.gsub(*AMENDMENTS, "\n\\0")
|
21
23
|
.gsub(/^(\s+)- /, '\1 - ')
|
22
24
|
end
|
23
25
|
|
@@ -26,6 +28,7 @@ module RuboCop
|
|
26
28
|
def unified_config
|
27
29
|
cops.each_with_object(config.dup) do |cop, unified|
|
28
30
|
next if SUBDEPARTMENTS.include?(cop)
|
31
|
+
next if AMENDMENTS.include?(cop)
|
29
32
|
|
30
33
|
unified[cop].merge!(descriptions.fetch(cop))
|
31
34
|
unified[cop]['Reference'] = COP_DOC_BASE_URL + cop.sub('RSpec/', '')
|
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.11.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-05-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -142,6 +142,7 @@ files:
|
|
142
142
|
- lib/rubocop/cop/rspec/capybara/current_path_expectation.rb
|
143
143
|
- lib/rubocop/cop/rspec/capybara/feature_methods.rb
|
144
144
|
- lib/rubocop/cop/rspec/capybara/visibility_matcher.rb
|
145
|
+
- lib/rubocop/cop/rspec/change_by_zero.rb
|
145
146
|
- lib/rubocop/cop/rspec/context_method.rb
|
146
147
|
- lib/rubocop/cop/rspec/context_wording.rb
|
147
148
|
- lib/rubocop/cop/rspec/describe_class.rb
|
@@ -262,14 +263,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
262
263
|
requirements:
|
263
264
|
- - ">="
|
264
265
|
- !ruby/object:Gem::Version
|
265
|
-
version: 2.
|
266
|
+
version: 2.6.0
|
266
267
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
268
|
requirements:
|
268
269
|
- - ">="
|
269
270
|
- !ruby/object:Gem::Version
|
270
271
|
version: '0'
|
271
272
|
requirements: []
|
272
|
-
rubygems_version: 3.
|
273
|
+
rubygems_version: 3.1.6
|
273
274
|
signing_key:
|
274
275
|
specification_version: 4
|
275
276
|
summary: Code style checking for RSpec files
|