rubocop-rspec 2.27.1 → 2.28.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 +4 -0
- data/config/obsoletion.yml +7 -0
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +17 -33
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +25 -69
- data/lib/rubocop/cop/rspec/rails/http_status.rb +51 -204
- data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +52 -135
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +29 -342
- data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +29 -92
- data/lib/rubocop/cop/rspec/rails/travel_around.rb +24 -82
- data/lib/rubocop/cop/rspec_cops.rb +2 -6
- data/lib/rubocop/rspec/config_formatter.rb +7 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +3 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bec4edcf5bcf8c729a8c897b3de5b80b68c08de7ee3b2a25cfa23518db43390
|
4
|
+
data.tar.gz: '0848c7f26310108d511c7986127016963432371d6554c679a8fb318387c05998'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72958ac870b50c4b3c5b91be2f18ab88d6b2abf64af255e56451c0a6f58b3fd570dd2a3452e7326af58af57cce9347e370978bd21685f6470bba50ea8d93b195
|
7
|
+
data.tar.gz: 34dc88c068186ac780e2c3e4ebc3048159c236acc4b685fd6630cd59de0910a3f4f181a310d0e2ff7d1b5f9a2609219118119ff23dee212b870b24f685aef195
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 2.28.0 (2024-03-30)
|
6
|
+
|
7
|
+
- Extract RSpec Rails cops to a separate repository, [`rubocop-rspec_rails`](https://github.com/rubocop/rubocop-rspec_rails). The `rubocop-rspec_rails` repository is a dependency of `rubocop-rspec` and the cops related to rspec-rails are aliased (`RSpec/Rails/Foo` == `RSpecRails/Foo`) until v3.0 is released, so the change will be invisible to users until then. ([@ydah])
|
8
|
+
|
5
9
|
## 2.27.1 (2024-03-03)
|
6
10
|
|
7
11
|
- Fix a false positive for `RSpec/RepeatedSubjectCall` when `subject.method_call`. ([@ydah])
|
data/config/obsoletion.yml
CHANGED
@@ -27,3 +27,10 @@ renamed:
|
|
27
27
|
RSpec/FactoryBot/FactoryClassName: FactoryBot/FactoryClassName
|
28
28
|
RSpec/FactoryBot/FactoryNameStyle: FactoryBot/FactoryNameStyle
|
29
29
|
RSpec/FactoryBot/SyntaxMethods: FactoryBot/SyntaxMethods
|
30
|
+
RSpec/Rails/AvoidSetupHook: RSpecRails/AvoidSetupHook
|
31
|
+
RSpec/Rails/HaveHttpStatus: RSpecRails/HaveHttpStatus
|
32
|
+
RSpec/Rails/HttpStatus: RSpecRails/HttpStatus
|
33
|
+
RSpec/Rails/InferredSpecType: RSpecRails/InferredSpecType
|
34
|
+
RSpec/Rails/MinitestAssertions: RSpecRails/MinitestAssertions
|
35
|
+
RSpec/Rails/NegationBeValid: RSpecRails/NegationBeValid
|
36
|
+
RSpec/Rails/TravelAround: RSpecRails/TravelAround
|
@@ -4,39 +4,23 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module Rails
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# #
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# #
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# @!method setup_call(node)
|
26
|
-
def_node_matcher :setup_call, <<~PATTERN
|
27
|
-
(block
|
28
|
-
$(send nil? :setup)
|
29
|
-
(args) _)
|
30
|
-
PATTERN
|
31
|
-
|
32
|
-
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
33
|
-
setup_call(node) do |setup|
|
34
|
-
add_offense(node) do |corrector|
|
35
|
-
corrector.replace setup, 'before'
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Checks that tests use RSpec `before` hook over Rails `setup`
|
9
|
+
# # method.
|
10
|
+
# #
|
11
|
+
# # @example
|
12
|
+
# # # bad
|
13
|
+
# # setup do
|
14
|
+
# # allow(foo).to receive(:bar)
|
15
|
+
# # end
|
16
|
+
# #
|
17
|
+
# # # good
|
18
|
+
# # before do
|
19
|
+
# # allow(foo).to receive(:bar)
|
20
|
+
# # end
|
21
|
+
# #
|
22
|
+
# class AvoidSetupHook < RuboCop::Cop::RSpecRails::Base; end
|
23
|
+
AvoidSetupHook = ::RuboCop::Cop::RSpecRails::AvoidSetupHook
|
40
24
|
end
|
41
25
|
end
|
42
26
|
end
|
@@ -4,75 +4,31 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module Rails
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# #
|
11
|
-
#
|
12
|
-
# expect(
|
13
|
-
#
|
14
|
-
# #
|
15
|
-
#
|
16
|
-
# expect(
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# #
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# #
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# #
|
26
|
-
#
|
27
|
-
# expect(
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
MSG =
|
33
|
-
'Prefer `expect(%<response>s).%<to>s ' \
|
34
|
-
'have_http_status(%<status>s)` over `%<bad_code>s`.'
|
35
|
-
|
36
|
-
RUNNERS = %i[to to_not not_to].to_set
|
37
|
-
RESTRICT_ON_SEND = RUNNERS
|
38
|
-
|
39
|
-
# @!method match_status(node)
|
40
|
-
def_node_matcher :match_status, <<~PATTERN
|
41
|
-
(send
|
42
|
-
(send nil? :expect
|
43
|
-
$(send $(send nil? #response_methods?) {:status :code})
|
44
|
-
)
|
45
|
-
$RUNNERS
|
46
|
-
$(send nil? {:be :eq :eql :equal} ({int str} $_))
|
47
|
-
)
|
48
|
-
PATTERN
|
49
|
-
|
50
|
-
def on_send(node) # rubocop:disable Metrics/MethodLength
|
51
|
-
match_status(node) do
|
52
|
-
|response_status, response_method, to, match, status|
|
53
|
-
return unless status.to_s.match?(/\A\d+\z/)
|
54
|
-
|
55
|
-
message = format(MSG, response: response_method.method_name,
|
56
|
-
to: to, status: status,
|
57
|
-
bad_code: node.source)
|
58
|
-
add_offense(node, message: message) do |corrector|
|
59
|
-
corrector.replace(response_status, response_method.method_name)
|
60
|
-
corrector.replace(match.loc.selector, 'have_http_status')
|
61
|
-
corrector.replace(match.first_argument, status.to_s)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def response_methods?(name)
|
69
|
-
response_methods.include?(name.to_s)
|
70
|
-
end
|
71
|
-
|
72
|
-
def response_methods
|
73
|
-
cop_config.fetch('ResponseMethods', [])
|
74
|
-
end
|
75
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Checks that tests use `have_http_status` instead of equality matchers.
|
9
|
+
# #
|
10
|
+
# # @example ResponseMethods: ['response', 'last_response'] (default)
|
11
|
+
# # # bad
|
12
|
+
# # expect(response.status).to be(200)
|
13
|
+
# # expect(last_response.code).to eq("200")
|
14
|
+
# #
|
15
|
+
# # # good
|
16
|
+
# # expect(response).to have_http_status(200)
|
17
|
+
# # expect(last_response).to have_http_status(200)
|
18
|
+
# #
|
19
|
+
# # @example ResponseMethods: ['foo_response']
|
20
|
+
# # # bad
|
21
|
+
# # expect(foo_response.status).to be(200)
|
22
|
+
# #
|
23
|
+
# # # good
|
24
|
+
# # expect(foo_response).to have_http_status(200)
|
25
|
+
# #
|
26
|
+
# # # also good
|
27
|
+
# # expect(response).to have_http_status(200)
|
28
|
+
# # expect(last_response).to have_http_status(200)
|
29
|
+
# #
|
30
|
+
# class HaveHttpStatus < ::RuboCop::Cop::Base; end
|
31
|
+
HaveHttpStatus = ::RuboCop::Cop::RSpecRails::HaveHttpStatus
|
76
32
|
end
|
77
33
|
end
|
78
34
|
end
|
@@ -1,213 +1,60 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rack/utils'
|
4
|
-
|
5
3
|
module RuboCop
|
6
4
|
module Cop
|
7
5
|
module RSpec
|
8
6
|
module Rails
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# `EnforcedStyle:
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# #
|
18
|
-
#
|
19
|
-
# it { is_expected.to have_http_status
|
20
|
-
# it { is_expected.to have_http_status
|
21
|
-
#
|
22
|
-
# #
|
23
|
-
#
|
24
|
-
# it { is_expected.to have_http_status :
|
25
|
-
# it { is_expected.to have_http_status :
|
26
|
-
# it { is_expected.to have_http_status :
|
27
|
-
# it { is_expected.to have_http_status :
|
28
|
-
#
|
29
|
-
#
|
30
|
-
# #
|
31
|
-
#
|
32
|
-
# it { is_expected.to have_http_status :
|
33
|
-
# it { is_expected.to have_http_status
|
34
|
-
#
|
35
|
-
# #
|
36
|
-
#
|
37
|
-
# it { is_expected.to have_http_status
|
38
|
-
# it { is_expected.to have_http_status
|
39
|
-
# it { is_expected.to have_http_status
|
40
|
-
# it { is_expected.to have_http_status :
|
41
|
-
#
|
42
|
-
#
|
43
|
-
# #
|
44
|
-
#
|
45
|
-
# it { is_expected.to have_http_status :
|
46
|
-
# it { is_expected.to have_http_status
|
47
|
-
# it { is_expected.to have_http_status
|
48
|
-
# it { is_expected.to have_http_status
|
49
|
-
# it { is_expected.to have_http_status
|
50
|
-
#
|
51
|
-
# #
|
52
|
-
#
|
53
|
-
# it { is_expected.to
|
54
|
-
# it { is_expected.to
|
55
|
-
# it { is_expected.to have_http_status :
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
RESTRICT_ON_SEND = %i[have_http_status].freeze
|
61
|
-
|
62
|
-
# @!method http_status(node)
|
63
|
-
def_node_matcher :http_status, <<~PATTERN
|
64
|
-
(send nil? :have_http_status ${int sym str})
|
65
|
-
PATTERN
|
66
|
-
|
67
|
-
def on_send(node)
|
68
|
-
http_status(node) do |arg|
|
69
|
-
return if arg.str_type? && arg.heredoc?
|
70
|
-
|
71
|
-
checker = checker_class.new(arg)
|
72
|
-
return unless checker.offensive?
|
73
|
-
|
74
|
-
add_offense(checker.offense_range,
|
75
|
-
message: checker.message) do |corrector|
|
76
|
-
corrector.replace(checker.offense_range, checker.prefer)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def checker_class
|
84
|
-
case style
|
85
|
-
when :symbolic
|
86
|
-
SymbolicStyleChecker
|
87
|
-
when :numeric
|
88
|
-
NumericStyleChecker
|
89
|
-
when :be_status
|
90
|
-
BeStatusStyleChecker
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# :nodoc:
|
95
|
-
class StyleCheckerBase
|
96
|
-
MSG = 'Prefer `%<prefer>s` over `%<current>s` ' \
|
97
|
-
'to describe HTTP status code.'
|
98
|
-
ALLOWED_STATUSES = %i[error success missing redirect].freeze
|
99
|
-
|
100
|
-
attr_reader :node
|
101
|
-
|
102
|
-
def initialize(node)
|
103
|
-
@node = node
|
104
|
-
end
|
105
|
-
|
106
|
-
def message
|
107
|
-
format(MSG, prefer: prefer, current: current)
|
108
|
-
end
|
109
|
-
|
110
|
-
def current
|
111
|
-
offense_range.source
|
112
|
-
end
|
113
|
-
|
114
|
-
def offense_range
|
115
|
-
node
|
116
|
-
end
|
117
|
-
|
118
|
-
def allowed_symbol?
|
119
|
-
node.sym_type? && ALLOWED_STATUSES.include?(node.value)
|
120
|
-
end
|
121
|
-
|
122
|
-
def custom_http_status_code?
|
123
|
-
node.int_type? &&
|
124
|
-
!::Rack::Utils::SYMBOL_TO_STATUS_CODE.value?(node.source.to_i)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
# :nodoc:
|
129
|
-
class SymbolicStyleChecker < StyleCheckerBase
|
130
|
-
def offensive?
|
131
|
-
!node.sym_type? && !custom_http_status_code?
|
132
|
-
end
|
133
|
-
|
134
|
-
def prefer
|
135
|
-
symbol.inspect
|
136
|
-
end
|
137
|
-
|
138
|
-
private
|
139
|
-
|
140
|
-
def symbol
|
141
|
-
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(number)
|
142
|
-
end
|
143
|
-
|
144
|
-
def number
|
145
|
-
node.value.to_i
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# :nodoc:
|
150
|
-
class NumericStyleChecker < StyleCheckerBase
|
151
|
-
def offensive?
|
152
|
-
!node.int_type? && !allowed_symbol?
|
153
|
-
end
|
154
|
-
|
155
|
-
def prefer
|
156
|
-
number.to_s
|
157
|
-
end
|
158
|
-
|
159
|
-
private
|
160
|
-
|
161
|
-
def symbol
|
162
|
-
node.value
|
163
|
-
end
|
164
|
-
|
165
|
-
def number
|
166
|
-
::Rack::Utils::SYMBOL_TO_STATUS_CODE[symbol.to_sym]
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
# :nodoc:
|
171
|
-
class BeStatusStyleChecker < StyleCheckerBase
|
172
|
-
def offensive?
|
173
|
-
(!node.sym_type? && !custom_http_status_code?) ||
|
174
|
-
(!node.int_type? && !allowed_symbol?)
|
175
|
-
end
|
176
|
-
|
177
|
-
def offense_range
|
178
|
-
node.parent
|
179
|
-
end
|
180
|
-
|
181
|
-
def prefer
|
182
|
-
if node.sym_type?
|
183
|
-
"be_#{node.value}"
|
184
|
-
elsif node.int_type?
|
185
|
-
"be_#{symbol}"
|
186
|
-
elsif node.str_type?
|
187
|
-
"be_#{normalize_str}"
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
private
|
192
|
-
|
193
|
-
def symbol
|
194
|
-
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(number)
|
195
|
-
end
|
196
|
-
|
197
|
-
def number
|
198
|
-
node.value.to_i
|
199
|
-
end
|
200
|
-
|
201
|
-
def normalize_str
|
202
|
-
str = node.value.to_s
|
203
|
-
if str.match?(/\A\d+\z/)
|
204
|
-
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(str.to_i)
|
205
|
-
else
|
206
|
-
str
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Enforces use of symbolic or numeric value to describe HTTP status.
|
9
|
+
# #
|
10
|
+
# # This cop inspects only `have_http_status` calls.
|
11
|
+
# # So, this cop does not check if a method starting with `be_*` is
|
12
|
+
# # used when setting for `EnforcedStyle: symbolic` or
|
13
|
+
# # `EnforcedStyle: numeric`.
|
14
|
+
# #
|
15
|
+
# # @example `EnforcedStyle: symbolic` (default)
|
16
|
+
# # # bad
|
17
|
+
# # it { is_expected.to have_http_status 200 }
|
18
|
+
# # it { is_expected.to have_http_status 404 }
|
19
|
+
# # it { is_expected.to have_http_status "403" }
|
20
|
+
# #
|
21
|
+
# # # good
|
22
|
+
# # it { is_expected.to have_http_status :ok }
|
23
|
+
# # it { is_expected.to have_http_status :not_found }
|
24
|
+
# # it { is_expected.to have_http_status :forbidden }
|
25
|
+
# # it { is_expected.to have_http_status :success }
|
26
|
+
# # it { is_expected.to have_http_status :error }
|
27
|
+
# #
|
28
|
+
# # @example `EnforcedStyle: numeric`
|
29
|
+
# # # bad
|
30
|
+
# # it { is_expected.to have_http_status :ok }
|
31
|
+
# # it { is_expected.to have_http_status :not_found }
|
32
|
+
# # it { is_expected.to have_http_status "forbidden" }
|
33
|
+
# #
|
34
|
+
# # # good
|
35
|
+
# # it { is_expected.to have_http_status 200 }
|
36
|
+
# # it { is_expected.to have_http_status 404 }
|
37
|
+
# # it { is_expected.to have_http_status 403 }
|
38
|
+
# # it { is_expected.to have_http_status :success }
|
39
|
+
# # it { is_expected.to have_http_status :error }
|
40
|
+
# #
|
41
|
+
# # @example `EnforcedStyle: be_status`
|
42
|
+
# # # bad
|
43
|
+
# # it { is_expected.to have_http_status :ok }
|
44
|
+
# # it { is_expected.to have_http_status :not_found }
|
45
|
+
# # it { is_expected.to have_http_status "forbidden" }
|
46
|
+
# # it { is_expected.to have_http_status 200 }
|
47
|
+
# # it { is_expected.to have_http_status 404 }
|
48
|
+
# # it { is_expected.to have_http_status "403" }
|
49
|
+
# #
|
50
|
+
# # # good
|
51
|
+
# # it { is_expected.to be_ok }
|
52
|
+
# # it { is_expected.to be_not_found }
|
53
|
+
# # it { is_expected.to have_http_status :success }
|
54
|
+
# # it { is_expected.to have_http_status :error }
|
55
|
+
# #
|
56
|
+
# class HttpStatus < RuboCop::Cop::RSpecRails::Base; end
|
57
|
+
HttpStatus = ::RuboCop::Cop::RSpecRails::HttpStatus
|
211
58
|
end
|
212
59
|
end
|
213
60
|
end
|
@@ -4,141 +4,58 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module Rails
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# #
|
20
|
-
# #
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# #
|
25
|
-
# #
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# #
|
30
|
-
# #
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# #
|
36
|
-
# #
|
37
|
-
# #
|
38
|
-
# #
|
39
|
-
#
|
40
|
-
# #
|
41
|
-
# #
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
# #
|
46
|
-
# #
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
# #
|
51
|
-
# #
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
# @param [RuboCop::AST::BlockNode] node
|
60
|
-
def on_block(node)
|
61
|
-
return unless example_group?(node)
|
62
|
-
|
63
|
-
pair_node = describe_with_type(node)
|
64
|
-
return unless pair_node
|
65
|
-
return unless inferred_type?(pair_node)
|
66
|
-
|
67
|
-
removable_node = detect_removable_node(pair_node)
|
68
|
-
add_offense(removable_node) do |corrector|
|
69
|
-
autocorrect(corrector, removable_node)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
alias on_numblock on_block
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
# @!method describe_with_type(node)
|
77
|
-
# @param [RuboCop::AST::BlockNode] node
|
78
|
-
# @return [RuboCop::AST::PairNode, nil]
|
79
|
-
def_node_matcher :describe_with_type, <<~PATTERN
|
80
|
-
(block
|
81
|
-
(send #rspec? #ExampleGroups.all
|
82
|
-
...
|
83
|
-
(hash <$(pair (sym :type) sym) ...>)
|
84
|
-
)
|
85
|
-
...
|
86
|
-
)
|
87
|
-
PATTERN
|
88
|
-
|
89
|
-
# @param [RuboCop::AST::Corrector] corrector
|
90
|
-
# @param [RuboCop::AST::Node] node
|
91
|
-
def autocorrect(corrector, node)
|
92
|
-
corrector.remove(remove_range(node))
|
93
|
-
end
|
94
|
-
|
95
|
-
# @param [RuboCop::AST::Node] node
|
96
|
-
# @return [Parser::Source::Range]
|
97
|
-
def remove_range(node)
|
98
|
-
if node.left_sibling
|
99
|
-
node.source_range.with(
|
100
|
-
begin_pos: node.left_sibling.source_range.end_pos
|
101
|
-
)
|
102
|
-
elsif node.right_sibling
|
103
|
-
node.source_range.with(
|
104
|
-
end_pos: node.right_sibling.source_range.begin_pos
|
105
|
-
)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# @param [RuboCop::AST::PairNode] node
|
110
|
-
# @return [RuboCop::AST::Node]
|
111
|
-
def detect_removable_node(node)
|
112
|
-
if node.parent.pairs.size == 1
|
113
|
-
node.parent
|
114
|
-
else
|
115
|
-
node
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# @return [String]
|
120
|
-
def file_path
|
121
|
-
processed_source.file_path
|
122
|
-
end
|
123
|
-
|
124
|
-
# @param [RuboCop::AST::PairNode] node
|
125
|
-
# @return [Boolean]
|
126
|
-
def inferred_type?(node)
|
127
|
-
inferred_type_from_file_path.inspect == node.value.source
|
128
|
-
end
|
129
|
-
|
130
|
-
# @return [Symbol, nil]
|
131
|
-
def inferred_type_from_file_path
|
132
|
-
inferences.find do |prefix, type|
|
133
|
-
break type.to_sym if file_path.include?("spec/#{prefix}/")
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# @return [Hash]
|
138
|
-
def inferences
|
139
|
-
cop_config['Inferences'] || {}
|
140
|
-
end
|
141
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Identifies redundant spec type.
|
9
|
+
# #
|
10
|
+
# # After setting up rspec-rails, you will have enabled
|
11
|
+
# # `config.infer_spec_type_from_file_location!` by default in
|
12
|
+
# # spec/rails_helper.rb. This cop works in conjunction with
|
13
|
+
# # this config.
|
14
|
+
# # If you disable this config, disable this cop as well.
|
15
|
+
# #
|
16
|
+
# # @safety
|
17
|
+
# # This cop is marked as unsafe because
|
18
|
+
# # `config.infer_spec_type_from_file_location!` may not be enabled.
|
19
|
+
# #
|
20
|
+
# # @example
|
21
|
+
# # # bad
|
22
|
+
# # # spec/models/user_spec.rb
|
23
|
+
# # RSpec.describe User, type: :model do
|
24
|
+
# # end
|
25
|
+
# #
|
26
|
+
# # # good
|
27
|
+
# # # spec/models/user_spec.rb
|
28
|
+
# # RSpec.describe User do
|
29
|
+
# # end
|
30
|
+
# #
|
31
|
+
# # # good
|
32
|
+
# # # spec/models/user_spec.rb
|
33
|
+
# # RSpec.describe User, type: :common do
|
34
|
+
# # end
|
35
|
+
# #
|
36
|
+
# # @example `Inferences` configuration
|
37
|
+
# # # .rubocop.yml
|
38
|
+
# # # RSpec/Rails/InferredSpecType:
|
39
|
+
# # # Inferences:
|
40
|
+
# # # services: service
|
41
|
+
# #
|
42
|
+
# # # bad
|
43
|
+
# # # spec/services/user_spec.rb
|
44
|
+
# # RSpec.describe User, type: :service do
|
45
|
+
# # end
|
46
|
+
# #
|
47
|
+
# # # good
|
48
|
+
# # # spec/services/user_spec.rb
|
49
|
+
# # RSpec.describe User do
|
50
|
+
# # end
|
51
|
+
# #
|
52
|
+
# # # good
|
53
|
+
# # # spec/services/user_spec.rb
|
54
|
+
# # RSpec.describe User, type: :common do
|
55
|
+
# # end
|
56
|
+
# #
|
57
|
+
# class InferredSpecType < RuboCop::Cop::RSpecRails::Base; end
|
58
|
+
InferredSpecType = ::RuboCop::Cop::RSpecRails::InferredSpecType
|
142
59
|
end
|
143
60
|
end
|
144
61
|
end
|