rubocop-rspec 2.8.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 +23 -0
- data/config/default.yml +44 -3
- data/lib/rubocop/cop/rspec/be_eq.rb +45 -0
- data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
- data/lib/rubocop/cop/rspec/be_nil.rb +74 -0
- 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 +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/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 +4 -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 +8 -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,25 @@
|
|
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
|
+
|
12
|
+
## 2.10.0 (2022-04-19)
|
13
|
+
|
14
|
+
* Fix a false positive for `RSpec/EmptyExampleGroup` when expectations in case statement. ([@ydah][])
|
15
|
+
* Add `RSpec/VerifiedDoubleReference` cop. ([@t3h2mas][])
|
16
|
+
* Make `RSpec/BeNil` cop configurable with a `be_nil` style and a `be` style. ([@bquorning][])
|
17
|
+
* Fix `Capybara/CurrentPathExpectation` autocorrect incompatible with `Style/TrailingCommaInArguments` autocorrect. ([@ydah][])
|
18
|
+
|
19
|
+
## 2.9.0 (2022-02-28)
|
20
|
+
|
21
|
+
* Add new `RSpec/BeNil` cop. ([@bquorning][])
|
22
|
+
* Add new `RSpec/BeEq` cop. ([@bquorning][])
|
23
|
+
|
5
24
|
## 2.8.0 (2022-01-24)
|
6
25
|
|
7
26
|
* Fix `RSpec/FactoryBot/SyntaxMethods` and `RSpec/Capybara/FeatureMethods` to inspect shared groups. ([@pirj][])
|
@@ -667,3 +686,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
667
686
|
[@leoarnold]: https://github.com/leoarnold
|
668
687
|
[@harry-graham]: https://github.com/harry-graham
|
669
688
|
[@oshiro3]: https://github.com/oshiro3
|
689
|
+
[@ydah]: https://github.com/ydah
|
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
|
@@ -142,12 +150,29 @@ RSpec/Be:
|
|
142
150
|
StyleGuide: https://rspec.rubystyle.guide/#be-matcher
|
143
151
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be
|
144
152
|
|
153
|
+
RSpec/BeEq:
|
154
|
+
Description: Check for expectations where `be(...)` can replace `eq(...)`.
|
155
|
+
Enabled: pending
|
156
|
+
VersionAdded: 2.9.0
|
157
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEq
|
158
|
+
|
145
159
|
RSpec/BeEql:
|
146
160
|
Description: Check for expectations where `be(...)` can replace `eql(...)`.
|
147
161
|
Enabled: true
|
148
162
|
VersionAdded: '1.7'
|
149
163
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql
|
150
164
|
|
165
|
+
RSpec/BeNil:
|
166
|
+
Description: Ensures a consistent style is used when matching `nil`.
|
167
|
+
Enabled: pending
|
168
|
+
EnforcedStyle: be_nil
|
169
|
+
SupportedStyles:
|
170
|
+
- be
|
171
|
+
- be_nil
|
172
|
+
VersionAdded: 2.9.0
|
173
|
+
VersionChanged: 2.10.0
|
174
|
+
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeNil
|
175
|
+
|
151
176
|
RSpec/BeforeAfterAll:
|
152
177
|
Description: Check that before/after(:all) isn't being used.
|
153
178
|
Enabled: true
|
@@ -159,6 +184,12 @@ RSpec/BeforeAfterAll:
|
|
159
184
|
StyleGuide: https://rspec.rubystyle.guide/#avoid-hooks-with-context-scope
|
160
185
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
|
161
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
|
+
|
162
193
|
RSpec/ContextMethod:
|
163
194
|
Description: "`context` should not be used for specifying methods."
|
164
195
|
Enabled: true
|
@@ -239,7 +270,7 @@ RSpec/DescribedClassModuleWrapping:
|
|
239
270
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping
|
240
271
|
|
241
272
|
RSpec/Dialect:
|
242
|
-
Description:
|
273
|
+
Description: Enforces custom RSpec dialects.
|
243
274
|
Enabled: false
|
244
275
|
PreferredMethods: {}
|
245
276
|
VersionAdded: '1.33'
|
@@ -749,6 +780,16 @@ RSpec/VariableName:
|
|
749
780
|
VersionChanged: '1.43'
|
750
781
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName
|
751
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
|
+
|
752
793
|
RSpec/VerifiedDoubles:
|
753
794
|
Description: Prefer using verifying doubles over normal doubles.
|
754
795
|
Enabled: true
|
@@ -760,13 +801,13 @@ RSpec/VerifiedDoubles:
|
|
760
801
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles
|
761
802
|
|
762
803
|
RSpec/VoidExpect:
|
763
|
-
Description:
|
804
|
+
Description: Checks void `expect()`.
|
764
805
|
Enabled: true
|
765
806
|
VersionAdded: '1.16'
|
766
807
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect
|
767
808
|
|
768
809
|
RSpec/Yield:
|
769
|
-
Description:
|
810
|
+
Description: Checks for calling a block within a stub.
|
770
811
|
Enabled: true
|
771
812
|
VersionAdded: '1.32'
|
772
813
|
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Check for expectations where `be(...)` can replace `eq(...)`.
|
7
|
+
#
|
8
|
+
# The `be` matcher compares by identity while the `eq` matcher compares
|
9
|
+
# using `==`. Booleans and nil can be compared by identity and therefore
|
10
|
+
# the `be` matcher is preferable as it is a more strict test.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# expect(foo).to eq(true)
|
16
|
+
# expect(foo).to eq(false)
|
17
|
+
# expect(foo).to eq(nil)
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# expect(foo).to be(true)
|
21
|
+
# expect(foo).to be(false)
|
22
|
+
# expect(foo).to be(nil)
|
23
|
+
#
|
24
|
+
class BeEq < Base
|
25
|
+
extend AutoCorrector
|
26
|
+
|
27
|
+
MSG = 'Prefer `be` over `eq`.'
|
28
|
+
RESTRICT_ON_SEND = %i[eq].freeze
|
29
|
+
|
30
|
+
# @!method eq_type_with_identity?(node)
|
31
|
+
def_node_matcher :eq_type_with_identity?, <<-PATTERN
|
32
|
+
(send nil? :eq {true false nil})
|
33
|
+
PATTERN
|
34
|
+
|
35
|
+
def on_send(node)
|
36
|
+
return unless eq_type_with_identity?(node)
|
37
|
+
|
38
|
+
add_offense(node.loc.selector) do |corrector|
|
39
|
+
corrector.replace(node.loc.selector, 'be')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
|
44
44
|
# @!method eql_type_with_identity(node)
|
45
45
|
def_node_matcher :eql_type_with_identity, <<-PATTERN
|
46
|
-
(send _ :to $(send nil? :eql {true false int float sym
|
46
|
+
(send _ :to $(send nil? :eql {true false int float sym nil}))
|
47
47
|
PATTERN
|
48
48
|
|
49
49
|
def on_send(node)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Ensures a consistent style is used when matching `nil`.
|
7
|
+
#
|
8
|
+
# You can either use the more specific `be_nil` matcher, or the more
|
9
|
+
# generic `be` matcher with a `nil` argument.
|
10
|
+
#
|
11
|
+
# This cop can be configured using the `EnforcedStyle` option
|
12
|
+
#
|
13
|
+
# @example `EnforcedStyle: be_nil` (default)
|
14
|
+
# # bad
|
15
|
+
# expect(foo).to be(nil)
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# expect(foo).to be_nil
|
19
|
+
#
|
20
|
+
# @example `EnforcedStyle: be`
|
21
|
+
# # bad
|
22
|
+
# expect(foo).to be_nil
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# expect(foo).to be(nil)
|
26
|
+
#
|
27
|
+
class BeNil < Base
|
28
|
+
extend AutoCorrector
|
29
|
+
include ConfigurableEnforcedStyle
|
30
|
+
|
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
|
39
|
+
|
40
|
+
# @!method nil_value_expectation?(node)
|
41
|
+
def_node_matcher :nil_value_expectation?, <<-PATTERN
|
42
|
+
(send nil? :be nil)
|
43
|
+
PATTERN
|
44
|
+
|
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)
|
65
|
+
return unless nil_value_expectation?(node)
|
66
|
+
|
67
|
+
add_offense(node, message: BE_NIL_MSG) do |corrector|
|
68
|
+
corrector.replace(node.loc.expression, 'be_nil')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
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,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))
|
@@ -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
|
@@ -21,8 +21,11 @@ require_relative 'rspec/align_right_let_brace'
|
|
21
21
|
require_relative 'rspec/any_instance'
|
22
22
|
require_relative 'rspec/around_block'
|
23
23
|
require_relative 'rspec/be'
|
24
|
+
require_relative 'rspec/be_eq'
|
24
25
|
require_relative 'rspec/be_eql'
|
26
|
+
require_relative 'rspec/be_nil'
|
25
27
|
require_relative 'rspec/before_after_all'
|
28
|
+
require_relative 'rspec/change_by_zero'
|
26
29
|
require_relative 'rspec/context_method'
|
27
30
|
require_relative 'rspec/context_wording'
|
28
31
|
require_relative 'rspec/describe_class'
|
@@ -95,6 +98,7 @@ require_relative 'rspec/subject_stub'
|
|
95
98
|
require_relative 'rspec/unspecified_exception'
|
96
99
|
require_relative 'rspec/variable_definition'
|
97
100
|
require_relative 'rspec/variable_name'
|
101
|
+
require_relative 'rspec/verified_double_reference'
|
98
102
|
require_relative 'rspec/verified_doubles'
|
99
103
|
require_relative 'rspec/void_expect'
|
100
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.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
|
@@ -135,11 +135,14 @@ files:
|
|
135
135
|
- lib/rubocop/cop/rspec/around_block.rb
|
136
136
|
- lib/rubocop/cop/rspec/base.rb
|
137
137
|
- lib/rubocop/cop/rspec/be.rb
|
138
|
+
- lib/rubocop/cop/rspec/be_eq.rb
|
138
139
|
- lib/rubocop/cop/rspec/be_eql.rb
|
140
|
+
- lib/rubocop/cop/rspec/be_nil.rb
|
139
141
|
- lib/rubocop/cop/rspec/before_after_all.rb
|
140
142
|
- lib/rubocop/cop/rspec/capybara/current_path_expectation.rb
|
141
143
|
- lib/rubocop/cop/rspec/capybara/feature_methods.rb
|
142
144
|
- lib/rubocop/cop/rspec/capybara/visibility_matcher.rb
|
145
|
+
- lib/rubocop/cop/rspec/change_by_zero.rb
|
143
146
|
- lib/rubocop/cop/rspec/context_method.rb
|
144
147
|
- lib/rubocop/cop/rspec/context_wording.rb
|
145
148
|
- lib/rubocop/cop/rspec/describe_class.rb
|
@@ -224,6 +227,7 @@ files:
|
|
224
227
|
- lib/rubocop/cop/rspec/unspecified_exception.rb
|
225
228
|
- lib/rubocop/cop/rspec/variable_definition.rb
|
226
229
|
- lib/rubocop/cop/rspec/variable_name.rb
|
230
|
+
- lib/rubocop/cop/rspec/verified_double_reference.rb
|
227
231
|
- lib/rubocop/cop/rspec/verified_doubles.rb
|
228
232
|
- lib/rubocop/cop/rspec/void_expect.rb
|
229
233
|
- lib/rubocop/cop/rspec/yield.rb
|
@@ -259,14 +263,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
259
263
|
requirements:
|
260
264
|
- - ">="
|
261
265
|
- !ruby/object:Gem::Version
|
262
|
-
version: 2.
|
266
|
+
version: 2.6.0
|
263
267
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
264
268
|
requirements:
|
265
269
|
- - ">="
|
266
270
|
- !ruby/object:Gem::Version
|
267
271
|
version: '0'
|
268
272
|
requirements: []
|
269
|
-
rubygems_version: 3.
|
273
|
+
rubygems_version: 3.1.6
|
270
274
|
signing_key:
|
271
275
|
specification_version: 4
|
272
276
|
summary: Code style checking for RSpec files
|