Skip to content

Commit

Permalink
Merge pull request #1307 from akiomik/have-http-status
Browse files Browse the repository at this point in the history
Add new `RSpec/Rails/HaveHttpStatus` cop
  • Loading branch information
bquorning authored Jul 1, 2022
2 parents d028400 + f05f6f8 commit bcde3ae
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,5 @@ RSpec/FactoryBot/SyntaxMethods:
Enabled: true
RSpec/Rails/AvoidSetupHook:
Enabled: true
RSpec/Rails/HaveHttpStatus:
Enabled: true
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Fix error in `RSpec/RSpec/FactoryBot/CreateList` cop for empty block. ([@tejasbubane][])
* Update `RSpec/MultipleExpectations` cop documentation with examples of aggregate_failures use. ([@edgibbs][])
* Declare autocorrect as unsafe for `RSpec/VerifiedDoubleReference`. ([@Drowze][])
* Add new `RSpec/Rails/HaveHttpStatus` cop. ([@akiomik][])

## 2.11.1 (2022-05-18)

Expand Down Expand Up @@ -706,3 +707,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
[@ngouy]: https://github.com/ngouy
[@edgibbs]: https://github.com/edgibbs
[@Drowze]: https://github.com/Drowze
[@akiomik]: https://github.com/akiomik
7 changes: 7 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,13 @@ RSpec/Rails/AvoidSetupHook:
VersionAdded: '2.4'
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/AvoidSetupHook

RSpec/Rails/HaveHttpStatus:
Description: Checks that tests use `have_http_status` instead of equality matchers.
Enabled: pending
SafeAutoCorrect: false
VersionAdded: "<<next>>"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HaveHttpStatus

RSpec/Rails/HttpStatus:
Description: Enforces use of symbolic or numeric value to describe HTTP status.
Enabled: true
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/pages/cops.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
=== Department xref:cops_rspec_rails.adoc[RSpec/Rails]

* xref:cops_rspec_rails.adoc#rspecrails/avoidsetuphook[RSpec/Rails/AvoidSetupHook]
* xref:cops_rspec_rails.adoc#rspecrails/havehttpstatus[RSpec/Rails/HaveHttpStatus]
* xref:cops_rspec_rails.adoc#rspecrails/httpstatus[RSpec/Rails/HttpStatus]

// END_COP_LIST
29 changes: 29 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec_rails.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@ end

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/AvoidSetupHook

== RSpec/Rails/HaveHttpStatus

|===
| Enabled by default | Safe | Supports autocorrection | Version Added | Version Changed

| Pending
| Yes
| Yes (Unsafe)
| <<next>>
| -
|===

Checks that tests use `have_http_status` instead of equality matchers.

=== Examples

[source,ruby]
----
# bad
expect(response.status).to be(200)
# good
expect(response).to have_http_status(200)
----

=== References

* https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HaveHttpStatus

== RSpec/Rails/HttpStatus

|===
Expand Down
47 changes: 47 additions & 0 deletions lib/rubocop/cop/rspec/rails/have_http_status.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

module RuboCop
module Cop
module RSpec
module Rails
# Checks that tests use `have_http_status` instead of equality matchers.
#
# @example
# # bad
# expect(response.status).to be(200)
#
# # good
# expect(response).to have_http_status(200)
#
class HaveHttpStatus < Base
extend AutoCorrector

MSG =
'Prefer `expect(response).%<to>s have_http_status(%<status>i)` ' \
'over `expect(response.status).%<to>s %<match>s`.'

# @!method match_status(node)
def_node_matcher :match_status, <<-PATTERN
(send
(send nil? :expect
$(send (send nil? :response) :status)
)
$#Runners.all
$(send nil? {:be :eq :eql :equal} (int $_))
)
PATTERN

def on_send(node)
match_status(node) do |response_status, to, match, status|
message = format(MSG, to: to, match: match.source, status: status)
add_offense(node, message: message) do |corrector|
corrector.replace(response_status.source_range, 'response')
corrector.replace(match.loc.selector, 'have_http_status')
end
end
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rspec_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require_relative 'rspec/factory_bot/syntax_methods'

require_relative 'rspec/rails/avoid_setup_hook'
require_relative 'rspec/rails/have_http_status'
begin
require_relative 'rspec/rails/http_status'
rescue LoadError
Expand Down
37 changes: 37 additions & 0 deletions spec/rubocop/cop/rspec/rails/have_http_status_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::RSpec::Rails::HaveHttpStatus do
it 'registers an offense for `expect(response.status).to be(200)`' do
expect_offense(<<~RUBY)
it { expect(response.status).to be(200) }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `expect(response).to have_http_status(200)` over `expect(response.status).to be(200)`.
RUBY

expect_correction(<<~RUBY)
it { expect(response).to have_http_status(200) }
RUBY
end

it 'registers an offense for `expect(response.status).not_to eq(404)`' do
expect_offense(<<~RUBY)
it { expect(response.status).not_to eq(404) }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `expect(response).not_to have_http_status(404)` over `expect(response.status).not_to eq(404)`.
RUBY

expect_correction(<<~RUBY)
it { expect(response).not_to have_http_status(404) }
RUBY
end

it 'does not register an offense for `is_expected.to be(200)`' do
expect_no_offenses(<<~RUBY)
it { is_expected.to be(200) }
RUBY
end

it 'does not register an offense for `expect(res.status).to be(200)`' do
expect_no_offenses(<<~RUBY)
it { expect(res.status).to be(200) }
RUBY
end
end

0 comments on commit bcde3ae

Please sign in to comment.