Skip to content

Commit e741eab

Browse files
committed
Handle unknown HTTP status codes for RSpecRails::HttpStatus cop
1 parent 41a3bd4 commit e741eab

File tree

4 files changed

+83
-9
lines changed

4 files changed

+83
-9
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Master (Unreleased)
44

5+
- Handle unknown HTTP status codes for `RSpecRails/HttpStatus` cop. ([@viralpraxis])
6+
57
## 2.30.0 (2024-06-12)
68

79
- Fix an runtime error for rubocop-rspec +3.0. ([@bquorning])
@@ -81,4 +83,5 @@
8183
[@r7kamura]: https://github.com/r7kamura
8284
[@splattael]: https://github.com/splattael
8385
[@tmaier]: https://github.com/tmaier
86+
[@viralpraxis]: https://github.com/viralpraxis
8487
[@ydah]: https://github.com/ydah

docs/modules/ROOT/pages/cops_rspecrails.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ This cop inspects only `have_http_status` calls.
115115
So, this cop does not check if a method starting with `be_*` is used
116116
when setting for `EnforcedStyle: symbolic` or
117117
`EnforcedStyle: numeric`.
118+
This cop is also capable of detecting unknown HTTP status codes.
118119
119120
=== Examples
120121
@@ -171,6 +172,15 @@ it { is_expected.to have_http_status :success }
171172
it { is_expected.to have_http_status :error }
172173
----
173174
175+
[source,ruby]
176+
----
177+
# bad
178+
it { is_expected.to have_http_status :oki_doki }
179+
180+
# good
181+
it { is_expected.to have_http_status :ok }
182+
----
183+
174184
=== Configurable attributes
175185
176186
|===

lib/rubocop/cop/rspec_rails/http_status.rb

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module RSpecRails
1515
# So, this cop does not check if a method starting with `be_*` is used
1616
# when setting for `EnforcedStyle: symbolic` or
1717
# `EnforcedStyle: numeric`.
18+
# This cop is also capable of detecting unknown HTTP status codes.
1819
#
1920
# @example `EnforcedStyle: symbolic` (default)
2021
# # bad
@@ -57,6 +58,12 @@ module RSpecRails
5758
# it { is_expected.to have_http_status :success }
5859
# it { is_expected.to have_http_status :error }
5960
#
61+
# @example
62+
# # bad
63+
# it { is_expected.to have_http_status :oki_doki }
64+
#
65+
# # good
66+
# it { is_expected.to have_http_status :ok }
6067
class HttpStatus < ::RuboCop::Cop::Base
6168
extend AutoCorrector
6269
include ConfigurableEnforcedStyle
@@ -67,7 +74,7 @@ class HttpStatus < ::RuboCop::Cop::Base
6774
(send nil? :have_http_status ${int sym str})
6875
PATTERN
6976

70-
def on_send(node)
77+
def on_send(node) # rubocop:disable Metrics/MethodLength
7178
return unless defined?(::Rack::Utils::SYMBOL_TO_STATUS_CODE)
7279

7380
http_status(node) do |arg|
@@ -78,6 +85,8 @@ def on_send(node)
7885

7986
add_offense(checker.offense_range,
8087
message: checker.message) do |corrector|
88+
next unless checker.autocorrectable?
89+
8190
corrector.replace(checker.offense_range, checker.prefer)
8291
end
8392
end
@@ -100,6 +109,7 @@ def checker_class
100109
class StyleCheckerBase
101110
MSG = 'Prefer `%<prefer>s` over `%<current>s` ' \
102111
'to describe HTTP status code.'
112+
MSG_UNKNOWN_STATUS_CODE = 'Unknown status code.'
103113
ALLOWED_STATUSES = %i[error success missing redirect].freeze
104114

105115
attr_reader :node
@@ -109,7 +119,15 @@ def initialize(node)
109119
end
110120

111121
def message
112-
format(MSG, prefer: prefer, current: current)
122+
if autocorrectable?
123+
format(MSG, prefer: prefer, current: current)
124+
else
125+
MSG_UNKNOWN_STATUS_CODE
126+
end
127+
end
128+
129+
def autocorrectable?
130+
true
113131
end
114132

115133
def current
@@ -136,6 +154,10 @@ def offensive?
136154
!node.sym_type? && !custom_http_status_code?
137155
end
138156

157+
def autocorrectable?
158+
!!symbol
159+
end
160+
139161
def prefer
140162
symbol.inspect
141163
end
@@ -157,6 +179,10 @@ def offensive?
157179
!node.int_type? && !allowed_symbol?
158180
end
159181

182+
def autocorrectable?
183+
!!number
184+
end
185+
160186
def prefer
161187
number.to_s
162188
end
@@ -179,22 +205,30 @@ def offensive?
179205
(!node.int_type? && !allowed_symbol?)
180206
end
181207

208+
def autocorrectable?
209+
!!status_code
210+
end
211+
182212
def offense_range
183213
node.parent
184214
end
185215

186216
def prefer
217+
"be_#{status_code}"
218+
end
219+
220+
private
221+
222+
def status_code
187223
if node.sym_type?
188-
"be_#{node.value}"
224+
node.value
189225
elsif node.int_type?
190-
"be_#{symbol}"
191-
elsif node.str_type?
192-
"be_#{normalize_str}"
226+
symbol
227+
else
228+
normalize_str
193229
end
194230
end
195231

196-
private
197-
198232
def symbol
199233
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(number)
200234
end
@@ -207,7 +241,7 @@ def normalize_str
207241
str = node.value.to_s
208242
if str.match?(/\A\d+\z/)
209243
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(str.to_i)
210-
else
244+
elsif ::Rack::Utils::SYMBOL_TO_STATUS_CODE.key?(str.to_sym)
211245
str
212246
end
213247
end

spec/rubocop/cop/rspec_rails/http_status_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@
8080
RUBY
8181
end
8282
end
83+
84+
it 'registers an offense for unknown status code' do
85+
expect_offense(<<~RUBY)
86+
it { is_expected.to have_http_status("some-custom-string") }
87+
^^^^^^^^^^^^^^^^^^^^ Unknown status code.
88+
RUBY
89+
90+
expect_no_corrections
91+
end
8392
end
8493

8594
context 'when EnforcedStyle is `numeric`' do
@@ -133,6 +142,15 @@
133142
RUBY
134143
end
135144

145+
it 'registers an offense for unknown status code' do
146+
expect_offense(<<~RUBY)
147+
it { is_expected.to have_http_status("some-custom-string") }
148+
^^^^^^^^^^^^^^^^^^^^ Unknown status code.
149+
RUBY
150+
151+
expect_no_corrections
152+
end
153+
136154
context 'with parenthesis' do
137155
it 'registers an offense when using symbolic value' do
138156
expect_offense(<<~RUBY)
@@ -237,6 +255,15 @@
237255
RUBY
238256
end
239257

258+
it 'registers an offense for unknown status code' do
259+
expect_offense(<<~RUBY)
260+
it { is_expected.to have_http_status("some-custom-string") }
261+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unknown status code.
262+
RUBY
263+
264+
expect_no_corrections
265+
end
266+
240267
context 'with parenthesis' do
241268
it 'registers an offense when using numeric value' do
242269
expect_offense(<<~RUBY)

0 commit comments

Comments
 (0)