From c5158ba90dee32b0ce53ac48ed7c1b14ae5d902b Mon Sep 17 00:00:00 2001 From: viralpraxis Date: Wed, 2 Oct 2024 23:54:56 +0300 Subject: [PATCH] Handle unknown HTTP status codes for `RSpecRails::HttpStatus` cop --- CHANGELOG.md | 3 ++ lib/rubocop/cop/rspec_rails/http_status.rb | 45 +++++++++++++++---- .../cop/rspec_rails/http_status_spec.rb | 27 +++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cad75145..3055402a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Master (Unreleased) +- Fix invalid autocorrection for `RSpecRails/HttpStatus` cop when unexpected object is passed. ([@viralpraxis]) + ## 2.30.0 (2024-06-12) - Fix an runtime error for rubocop-rspec +3.0. ([@bquorning]) @@ -81,4 +83,5 @@ [@r7kamura]: https://github.com/r7kamura [@splattael]: https://github.com/splattael [@tmaier]: https://github.com/tmaier +[@viralpraxis]: https://github.com/viralpraxis [@ydah]: https://github.com/ydah diff --git a/lib/rubocop/cop/rspec_rails/http_status.rb b/lib/rubocop/cop/rspec_rails/http_status.rb index 3d200b22..bb7fcf36 100644 --- a/lib/rubocop/cop/rspec_rails/http_status.rb +++ b/lib/rubocop/cop/rspec_rails/http_status.rb @@ -67,7 +67,7 @@ class HttpStatus < ::RuboCop::Cop::Base (send nil? :have_http_status ${int sym str}) PATTERN - def on_send(node) + def on_send(node) # rubocop:disable Metrics/MethodLength return unless defined?(::Rack::Utils::SYMBOL_TO_STATUS_CODE) http_status(node) do |arg| @@ -78,6 +78,8 @@ def on_send(node) add_offense(checker.offense_range, message: checker.message) do |corrector| + next unless checker.autocorrectable? + corrector.replace(checker.offense_range, checker.prefer) end end @@ -100,6 +102,7 @@ def checker_class class StyleCheckerBase MSG = 'Prefer `%s` over `%s` ' \ 'to describe HTTP status code.' + MSG_UNKNOWN_STATUS_CODE = 'Unknown status code.' ALLOWED_STATUSES = %i[error success missing redirect].freeze attr_reader :node @@ -109,7 +112,15 @@ def initialize(node) end def message - format(MSG, prefer: prefer, current: current) + if autocorrectable? + format(MSG, prefer: prefer, current: current) + else + MSG_UNKNOWN_STATUS_CODE + end + end + + def autocorrectable? + true end def current @@ -136,6 +147,10 @@ def offensive? !node.sym_type? && !custom_http_status_code? end + def autocorrectable? + !!symbol + end + def prefer symbol.inspect end @@ -157,6 +172,10 @@ def offensive? !node.int_type? && !allowed_symbol? end + def autocorrectable? + !!number + end + def prefer number.to_s end @@ -179,22 +198,30 @@ def offensive? (!node.int_type? && !allowed_symbol?) end + def autocorrectable? + !!status_code + end + def offense_range node.parent end def prefer + "be_#{status_code}" + end + + private + + def status_code if node.sym_type? - "be_#{node.value}" + node.value elsif node.int_type? - "be_#{symbol}" - elsif node.str_type? - "be_#{normalize_str}" + symbol + else + normalize_str end end - private - def symbol ::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(number) end @@ -207,7 +234,7 @@ def normalize_str str = node.value.to_s if str.match?(/\A\d+\z/) ::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(str.to_i) - else + elsif ::Rack::Utils::SYMBOL_TO_STATUS_CODE.key?(str.to_sym) str end end diff --git a/spec/rubocop/cop/rspec_rails/http_status_spec.rb b/spec/rubocop/cop/rspec_rails/http_status_spec.rb index a61abb74..2b8b9884 100644 --- a/spec/rubocop/cop/rspec_rails/http_status_spec.rb +++ b/spec/rubocop/cop/rspec_rails/http_status_spec.rb @@ -80,6 +80,15 @@ RUBY end end + + it 'registers an offense for unknown status code' do + expect_offense(<<~RUBY) + it { is_expected.to have_http_status("some-custom-string") } + ^^^^^^^^^^^^^^^^^^^^ Unknown status code. + RUBY + + expect_no_corrections + end end context 'when EnforcedStyle is `numeric`' do @@ -133,6 +142,15 @@ RUBY end + it 'registers an offense for unknown status code' do + expect_offense(<<~RUBY) + it { is_expected.to have_http_status("some-custom-string") } + ^^^^^^^^^^^^^^^^^^^^ Unknown status code. + RUBY + + expect_no_corrections + end + context 'with parenthesis' do it 'registers an offense when using symbolic value' do expect_offense(<<~RUBY) @@ -237,6 +255,15 @@ RUBY end + it 'registers an offense for unknown status code' do + expect_offense(<<~RUBY) + it { is_expected.to have_http_status("some-custom-string") } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unknown status code. + RUBY + + expect_no_corrections + end + context 'with parenthesis' do it 'registers an offense when using numeric value' do expect_offense(<<~RUBY)