rubocop-rspec 2.9.0 → 2.11.1
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 +22 -0
- data/config/default.yml +33 -4
- data/lib/rubocop/cop/rspec/be_nil.rb +41 -7
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +4 -0
- 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/empty_example_group.rb +6 -6
- data/lib/rubocop/cop/rspec/expect_change.rb +10 -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/verified_double_reference.rb +111 -0
- 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 +2 -0
- data/lib/rubocop/rspec/config_formatter.rb +3 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +14 -9
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 741b2b87f823e6fab2b693b917568362674a686183a1d00e11fbc24fecf8ae53
|
|
4
|
+
data.tar.gz: '089bcc60333425fe0469071f12b52f92671a442274b179f50c716fce1e0a1064'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4f32ff6a813bcb2b427f13541c519d1da616cd051b7fbfbf4d8100fecf4e120e6626271623bd35833555061ef0c19e858934e07c6a8ed72a24cade03b1a59fee
|
|
7
|
+
data.tar.gz: 29929728390c1ff9d6804c5babb614649966a60faccacc140f626e4eb78154eff39bb91fc38162fcfcdcdcbbb9593bdad8256f8471867e0dcb5b00abc047c544
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## Master (Unreleased)
|
|
4
4
|
|
|
5
|
+
## 2.11.1 (2022-05-18)
|
|
6
|
+
|
|
7
|
+
* Fix a regression in `RSpec/ExpectChange` flagging chained method calls. ([@pirj][])
|
|
8
|
+
|
|
9
|
+
## 2.11.0 (2022-05-18)
|
|
10
|
+
|
|
11
|
+
* Drop Ruby 2.5 support. ([@ydah][])
|
|
12
|
+
* Add new `RSpec/ChangeByZero` cop. ([@ydah][])
|
|
13
|
+
* Improve `RSpec/ExpectChange` to detect namespaced and top-level constants. ([@M-Yamashita01][])
|
|
14
|
+
* Introduce an amendment to `Metrics/BlockLength` to exclude spec files. ([@luke-hill][])
|
|
15
|
+
|
|
16
|
+
## 2.10.0 (2022-04-19)
|
|
17
|
+
|
|
18
|
+
* Fix a false positive for `RSpec/EmptyExampleGroup` when expectations in case statement. ([@ydah][])
|
|
19
|
+
* Add `RSpec/VerifiedDoubleReference` cop. ([@t3h2mas][])
|
|
20
|
+
* Make `RSpec/BeNil` cop configurable with a `be_nil` style and a `be` style. ([@bquorning][])
|
|
21
|
+
* Fix `Capybara/CurrentPathExpectation` autocorrect incompatible with `Style/TrailingCommaInArguments` autocorrect. ([@ydah][])
|
|
22
|
+
|
|
5
23
|
## 2.9.0 (2022-02-28)
|
|
6
24
|
|
|
7
25
|
* Add new `RSpec/BeNil` cop. ([@bquorning][])
|
|
@@ -672,3 +690,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
|
672
690
|
[@leoarnold]: https://github.com/leoarnold
|
|
673
691
|
[@harry-graham]: https://github.com/harry-graham
|
|
674
692
|
[@oshiro3]: https://github.com/oshiro3
|
|
693
|
+
[@ydah]: https://github.com/ydah
|
|
694
|
+
[@t3h2mas]: https://github.com/t3h2mas
|
|
695
|
+
[@M-Yamashita01]: https://github.com/M-Yamashita01
|
|
696
|
+
[@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
|
|
@@ -155,9 +163,14 @@ RSpec/BeEql:
|
|
|
155
163
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql
|
|
156
164
|
|
|
157
165
|
RSpec/BeNil:
|
|
158
|
-
Description:
|
|
166
|
+
Description: Ensures a consistent style is used when matching `nil`.
|
|
159
167
|
Enabled: pending
|
|
168
|
+
EnforcedStyle: be_nil
|
|
169
|
+
SupportedStyles:
|
|
170
|
+
- be
|
|
171
|
+
- be_nil
|
|
160
172
|
VersionAdded: 2.9.0
|
|
173
|
+
VersionChanged: 2.10.0
|
|
161
174
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeNil
|
|
162
175
|
|
|
163
176
|
RSpec/BeforeAfterAll:
|
|
@@ -171,6 +184,12 @@ RSpec/BeforeAfterAll:
|
|
|
171
184
|
StyleGuide: https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope
|
|
172
185
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
|
|
173
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
|
+
|
|
174
193
|
RSpec/ContextMethod:
|
|
175
194
|
Description: "`context` should not be used for specifying methods."
|
|
176
195
|
Enabled: true
|
|
@@ -251,7 +270,7 @@ RSpec/DescribedClassModuleWrapping:
|
|
|
251
270
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping
|
|
252
271
|
|
|
253
272
|
RSpec/Dialect:
|
|
254
|
-
Description:
|
|
273
|
+
Description: Enforces custom RSpec dialects.
|
|
255
274
|
Enabled: false
|
|
256
275
|
PreferredMethods: {}
|
|
257
276
|
VersionAdded: '1.33'
|
|
@@ -761,6 +780,16 @@ RSpec/VariableName:
|
|
|
761
780
|
VersionChanged: '1.43'
|
|
762
781
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName
|
|
763
782
|
|
|
783
|
+
RSpec/VerifiedDoubleReference:
|
|
784
|
+
Description: Checks for consistent verified double reference style.
|
|
785
|
+
Enabled: pending
|
|
786
|
+
EnforcedStyle: constant
|
|
787
|
+
SupportedStyles:
|
|
788
|
+
- constant
|
|
789
|
+
- string
|
|
790
|
+
VersionAdded: 2.10.0
|
|
791
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubleReference
|
|
792
|
+
|
|
764
793
|
RSpec/VerifiedDoubles:
|
|
765
794
|
Description: Prefer using verifying doubles over normal doubles.
|
|
766
795
|
Enabled: true
|
|
@@ -772,13 +801,13 @@ RSpec/VerifiedDoubles:
|
|
|
772
801
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles
|
|
773
802
|
|
|
774
803
|
RSpec/VoidExpect:
|
|
775
|
-
Description:
|
|
804
|
+
Description: Checks void `expect()`.
|
|
776
805
|
Enabled: true
|
|
777
806
|
VersionAdded: '1.16'
|
|
778
807
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect
|
|
779
808
|
|
|
780
809
|
RSpec/Yield:
|
|
781
|
-
Description:
|
|
810
|
+
Description: Checks for calling a block within a stub.
|
|
782
811
|
Enabled: true
|
|
783
812
|
VersionAdded: '1.32'
|
|
784
813
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield
|
|
@@ -3,24 +3,39 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module RSpec
|
|
6
|
-
#
|
|
6
|
+
# Ensures a consistent style is used when matching `nil`.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
8
|
+
# You can either use the more specific `be_nil` matcher, or the more
|
|
9
|
+
# generic `be` matcher with a `nil` argument.
|
|
10
10
|
#
|
|
11
|
-
#
|
|
11
|
+
# This cop can be configured using the `EnforcedStyle` option
|
|
12
12
|
#
|
|
13
|
+
# @example `EnforcedStyle: be_nil` (default)
|
|
13
14
|
# # bad
|
|
14
15
|
# expect(foo).to be(nil)
|
|
15
16
|
#
|
|
16
17
|
# # good
|
|
17
18
|
# expect(foo).to be_nil
|
|
18
19
|
#
|
|
20
|
+
# @example `EnforcedStyle: be`
|
|
21
|
+
# # bad
|
|
22
|
+
# expect(foo).to be_nil
|
|
23
|
+
#
|
|
24
|
+
# # good
|
|
25
|
+
# expect(foo).to be(nil)
|
|
26
|
+
#
|
|
19
27
|
class BeNil < Base
|
|
20
28
|
extend AutoCorrector
|
|
29
|
+
include ConfigurableEnforcedStyle
|
|
21
30
|
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
BE_MSG = 'Prefer `be(nil)` over `be_nil`.'
|
|
32
|
+
BE_NIL_MSG = 'Prefer `be_nil` over `be(nil)`.'
|
|
33
|
+
RESTRICT_ON_SEND = %i[be be_nil].freeze
|
|
34
|
+
|
|
35
|
+
# @!method be_nil_matcher?(node)
|
|
36
|
+
def_node_matcher :be_nil_matcher?, <<-PATTERN
|
|
37
|
+
(send nil? :be_nil)
|
|
38
|
+
PATTERN
|
|
24
39
|
|
|
25
40
|
# @!method nil_value_expectation?(node)
|
|
26
41
|
def_node_matcher :nil_value_expectation?, <<-PATTERN
|
|
@@ -28,9 +43,28 @@ module RuboCop
|
|
|
28
43
|
PATTERN
|
|
29
44
|
|
|
30
45
|
def on_send(node)
|
|
46
|
+
case style
|
|
47
|
+
when :be
|
|
48
|
+
check_be_style(node)
|
|
49
|
+
when :be_nil
|
|
50
|
+
check_be_nil_style(node)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def check_be_style(node)
|
|
57
|
+
return unless be_nil_matcher?(node)
|
|
58
|
+
|
|
59
|
+
add_offense(node, message: BE_MSG) do |corrector|
|
|
60
|
+
corrector.replace(node.loc.expression, 'be(nil)')
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def check_be_nil_style(node)
|
|
31
65
|
return unless nil_value_expectation?(node)
|
|
32
66
|
|
|
33
|
-
add_offense(node) do |corrector|
|
|
67
|
+
add_offense(node, message: BE_NIL_MSG) do |corrector|
|
|
34
68
|
corrector.replace(node.loc.expression, 'be_nil')
|
|
35
69
|
end
|
|
36
70
|
end
|
|
@@ -52,6 +52,10 @@ module RuboCop
|
|
|
52
52
|
$(send nil? :match (str $_)))
|
|
53
53
|
PATTERN
|
|
54
54
|
|
|
55
|
+
def self.autocorrect_incompatible_with
|
|
56
|
+
[Style::TrailingCommaInArguments]
|
|
57
|
+
end
|
|
58
|
+
|
|
55
59
|
def on_send(node)
|
|
56
60
|
expectation_set_on_current_path(node) do
|
|
57
61
|
add_offense(node.loc.selector) do |corrector|
|
|
@@ -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?
|
|
@@ -145,7 +145,7 @@ module RuboCop
|
|
|
145
145
|
return true unless body
|
|
146
146
|
return false if conditionals_with_examples?(body)
|
|
147
147
|
|
|
148
|
-
if body.if_type?
|
|
148
|
+
if body.if_type? || body.case_type?
|
|
149
149
|
!examples_in_branches?(body)
|
|
150
150
|
else
|
|
151
151
|
!examples?(body)
|
|
@@ -153,15 +153,15 @@ module RuboCop
|
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
def conditionals_with_examples?(body)
|
|
156
|
-
return unless body.begin_type?
|
|
156
|
+
return unless body.begin_type? || body.case_type?
|
|
157
157
|
|
|
158
|
-
body.each_descendant(:if).any? do |
|
|
159
|
-
examples_in_branches?(
|
|
158
|
+
body.each_descendant(:if, :case).any? do |condition_node|
|
|
159
|
+
examples_in_branches?(condition_node)
|
|
160
160
|
end
|
|
161
161
|
end
|
|
162
162
|
|
|
163
|
-
def examples_in_branches?(
|
|
164
|
-
|
|
163
|
+
def examples_in_branches?(condition_node)
|
|
164
|
+
condition_node.branches.any? { |branch| examples?(branch) }
|
|
165
165
|
end
|
|
166
166
|
end
|
|
167
167
|
end
|
|
@@ -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,13 @@ module RuboCop
|
|
|
47
47
|
(block
|
|
48
48
|
(send nil? :change)
|
|
49
49
|
(args)
|
|
50
|
-
(send
|
|
50
|
+
(send
|
|
51
|
+
${
|
|
52
|
+
(send nil? _) # change { user.name }
|
|
53
|
+
const # change { User.count }
|
|
54
|
+
}
|
|
55
|
+
$_
|
|
56
|
+
)
|
|
51
57
|
)
|
|
52
58
|
PATTERN
|
|
53
59
|
|
|
@@ -67,9 +73,9 @@ module RuboCop
|
|
|
67
73
|
return unless style == :method_call
|
|
68
74
|
|
|
69
75
|
expect_change_with_block(node) do |receiver, message|
|
|
70
|
-
msg = format(MSG_BLOCK, obj: receiver, attr: message)
|
|
76
|
+
msg = format(MSG_BLOCK, obj: receiver.source, attr: message)
|
|
71
77
|
add_offense(node, message: msg) do |corrector|
|
|
72
|
-
replacement = "change(#{receiver}, :#{message})"
|
|
78
|
+
replacement = "change(#{receiver.source}, :#{message})"
|
|
73
79
|
corrector.replace(node, replacement)
|
|
74
80
|
end
|
|
75
81
|
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))
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module RSpec
|
|
6
|
+
# Checks for consistent verified double reference style.
|
|
7
|
+
#
|
|
8
|
+
# Only investigates references that are one of the supported styles.
|
|
9
|
+
#
|
|
10
|
+
# @see https://relishapp.com/rspec/rspec-mocks/docs/verifying-doubles
|
|
11
|
+
#
|
|
12
|
+
# This cop can be configured in your configuration using the
|
|
13
|
+
# `EnforcedStyle` option and supports `--auto-gen-config`.
|
|
14
|
+
#
|
|
15
|
+
# @example `EnforcedStyle: constant` (default)
|
|
16
|
+
# # bad
|
|
17
|
+
# let(:foo) do
|
|
18
|
+
# instance_double('ClassName', method_name: 'returned_value')
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# # good
|
|
22
|
+
# let(:foo) do
|
|
23
|
+
# instance_double(ClassName, method_name: 'returned_value')
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# @example `EnforcedStyle: string`
|
|
27
|
+
# # bad
|
|
28
|
+
# let(:foo) do
|
|
29
|
+
# instance_double(ClassName, method_name: 'returned_value')
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# # good
|
|
33
|
+
# let(:foo) do
|
|
34
|
+
# instance_double('ClassName', method_name: 'returned_value')
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# @example Reference is not in the supported style list. No enforcement
|
|
38
|
+
#
|
|
39
|
+
# # good
|
|
40
|
+
# let(:foo) do
|
|
41
|
+
# instance_double(@klass, method_name: 'returned_value')
|
|
42
|
+
# end
|
|
43
|
+
class VerifiedDoubleReference < Base
|
|
44
|
+
extend AutoCorrector
|
|
45
|
+
include ConfigurableEnforcedStyle
|
|
46
|
+
|
|
47
|
+
MSG = 'Use a %<style>s class reference for verified doubles.'
|
|
48
|
+
|
|
49
|
+
RESTRICT_ON_SEND = Set[
|
|
50
|
+
:class_double,
|
|
51
|
+
:class_spy,
|
|
52
|
+
:instance_double,
|
|
53
|
+
:instance_spy,
|
|
54
|
+
:mock_model,
|
|
55
|
+
:object_double,
|
|
56
|
+
:object_spy,
|
|
57
|
+
:stub_model
|
|
58
|
+
].freeze
|
|
59
|
+
|
|
60
|
+
REFERENCE_TYPE_STYLES = {
|
|
61
|
+
str: :string,
|
|
62
|
+
const: :constant
|
|
63
|
+
}.freeze
|
|
64
|
+
|
|
65
|
+
# @!method verified_double(node)
|
|
66
|
+
def_node_matcher :verified_double, <<~PATTERN
|
|
67
|
+
(send
|
|
68
|
+
nil?
|
|
69
|
+
RESTRICT_ON_SEND
|
|
70
|
+
$_class_reference
|
|
71
|
+
...)
|
|
72
|
+
PATTERN
|
|
73
|
+
|
|
74
|
+
def on_send(node)
|
|
75
|
+
verified_double(node) do |class_reference|
|
|
76
|
+
break correct_style_detected unless opposing_style?(class_reference)
|
|
77
|
+
|
|
78
|
+
message = format(MSG, style: style)
|
|
79
|
+
expression = class_reference.loc.expression
|
|
80
|
+
|
|
81
|
+
add_offense(expression, message: message) do |corrector|
|
|
82
|
+
violation = class_reference.children.last.to_s
|
|
83
|
+
corrector.replace(expression, correct_style(violation))
|
|
84
|
+
|
|
85
|
+
opposite_style_detected
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def opposing_style?(class_reference)
|
|
93
|
+
class_reference_style = REFERENCE_TYPE_STYLES[class_reference.type]
|
|
94
|
+
|
|
95
|
+
# Only enforce supported styles
|
|
96
|
+
return false unless class_reference_style
|
|
97
|
+
|
|
98
|
+
class_reference_style != style
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def correct_style(violation)
|
|
102
|
+
if style == :string
|
|
103
|
+
"'#{violation}'"
|
|
104
|
+
else
|
|
105
|
+
violation
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -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'
|
|
@@ -97,6 +98,7 @@ require_relative 'rspec/subject_stub'
|
|
|
97
98
|
require_relative 'rspec/unspecified_exception'
|
|
98
99
|
require_relative 'rspec/variable_definition'
|
|
99
100
|
require_relative 'rspec/variable_name'
|
|
101
|
+
require_relative 'rspec/verified_double_reference'
|
|
100
102
|
require_relative 'rspec/verified_doubles'
|
|
101
103
|
require_relative 'rspec/void_expect'
|
|
102
104
|
require_relative 'rspec/yield'
|
|
@@ -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/', '')
|
data/lib/rubocop-rspec.rb
CHANGED
|
@@ -37,16 +37,21 @@ require_relative 'rubocop/cop/rspec_cops'
|
|
|
37
37
|
# We have to register our autocorrect incompatibilities in RuboCop's cops
|
|
38
38
|
# as well so we do not hit infinite loops
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
[RSpec::AlignLeftLetBrace, RSpec::AlignRightLetBrace]
|
|
46
|
-
end
|
|
47
|
-
end
|
|
40
|
+
RuboCop::Cop::Layout::ExtraSpacing.singleton_class.prepend(
|
|
41
|
+
Module.new do
|
|
42
|
+
def autocorrect_incompatible_with
|
|
43
|
+
super.push(RuboCop::Cop::RSpec::AlignLeftLetBrace)
|
|
44
|
+
.push(RuboCop::Cop::RSpec::AlignRightLetBrace)
|
|
48
45
|
end
|
|
49
46
|
end
|
|
50
|
-
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
RuboCop::Cop::Style::TrailingCommaInArguments.singleton_class.prepend(
|
|
50
|
+
Module.new do
|
|
51
|
+
def autocorrect_incompatible_with
|
|
52
|
+
super.push(RuboCop::Cop::RSpec::Capybara::CurrentPathExpectation)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
)
|
|
51
56
|
|
|
52
57
|
RuboCop::AST::Node.include(RuboCop::RSpec::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: 2.
|
|
4
|
+
version: 2.11.1
|
|
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
|
|
@@ -226,6 +227,7 @@ files:
|
|
|
226
227
|
- lib/rubocop/cop/rspec/unspecified_exception.rb
|
|
227
228
|
- lib/rubocop/cop/rspec/variable_definition.rb
|
|
228
229
|
- lib/rubocop/cop/rspec/variable_name.rb
|
|
230
|
+
- lib/rubocop/cop/rspec/verified_double_reference.rb
|
|
229
231
|
- lib/rubocop/cop/rspec/verified_doubles.rb
|
|
230
232
|
- lib/rubocop/cop/rspec/void_expect.rb
|
|
231
233
|
- lib/rubocop/cop/rspec/yield.rb
|
|
@@ -261,14 +263,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
261
263
|
requirements:
|
|
262
264
|
- - ">="
|
|
263
265
|
- !ruby/object:Gem::Version
|
|
264
|
-
version: 2.
|
|
266
|
+
version: 2.6.0
|
|
265
267
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
266
268
|
requirements:
|
|
267
269
|
- - ">="
|
|
268
270
|
- !ruby/object:Gem::Version
|
|
269
271
|
version: '0'
|
|
270
272
|
requirements: []
|
|
271
|
-
rubygems_version: 3.
|
|
273
|
+
rubygems_version: 3.1.6
|
|
272
274
|
signing_key:
|
|
273
275
|
specification_version: 4
|
|
274
276
|
summary: Code style checking for RSpec files
|