summaryrefslogtreecommitdiff
path: root/rubocop/cop
diff options
context:
space:
mode:
Diffstat (limited to 'rubocop/cop')
-rw-r--r--rubocop/cop/rspec/have_gitlab_http_status.rb86
1 files changed, 61 insertions, 25 deletions
diff --git a/rubocop/cop/rspec/have_gitlab_http_status.rb b/rubocop/cop/rspec/have_gitlab_http_status.rb
index 6b179720060..d61fb9f2368 100644
--- a/rubocop/cop/rspec/have_gitlab_http_status.rb
+++ b/rubocop/cop/rspec/have_gitlab_http_status.rb
@@ -15,39 +15,67 @@ module RuboCop
# expect(response).to have_http_status(200)
# expect(response).to have_http_status(:ok)
# expect(response).to have_gitlab_http_status(200)
+ # expect(response.status).to eq(200)
+ # expect(response.status).not_to eq(200)
#
# # good
# expect(response).to have_gitlab_http_status(:ok)
+ # expect(response).not_to have_gitlab_http_status(:ok)
#
class HaveGitlabHttpStatus < RuboCop::Cop::Cop
CODE_TO_SYMBOL = Rack::Utils::SYMBOL_TO_STATUS_CODE.invert
MSG_MATCHER_NAME =
- 'Use `have_gitlab_http_status` instead of `have_http_status`.'
+ 'Prefer `have_gitlab_http_status` over `have_http_status`.'
- MSG_STATUS =
+ MSG_NUMERIC_STATUS =
'Prefer named HTTP status `%{name}` over ' \
'its numeric representation `%{code}`.'
- MSG_UNKNOWN = 'HTTP status `%{code}` is unknown. ' \
+ MSG_RESPONSE_STATUS =
+ 'Prefer `have_gitlab_http_status` matcher over ' \
+ '`response.status`.'
+
+ MSG_UNKNOWN_STATUS = 'HTTP status `%{code}` is unknown. ' \
'Please provide a valid one or disable this cop.'
MSG_DOCS_LINK = 'https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#have_gitlab_http_status'
REPLACEMENT = 'have_gitlab_http_status(%{arg})'
+ REPLACEMENT_RESPONSE_STATUS =
+ 'expect(response).%{expectation} have_gitlab_http_status(%{arg})'
+
def_node_matcher :have_http_status?, <<~PATTERN
- (
- send nil?
- {
- :have_http_status
- :have_gitlab_http_status
- }
+ (send nil?
+ { :have_http_status :have_gitlab_http_status }
_
)
PATTERN
+ def_node_matcher :response_status_eq?, <<~PATTERN
+ (send
+ (send nil? :expect
+ (send
+ (send nil? :response) :status)) ${ :to :not_to }
+ (send nil? :eq
+ (int $_)))
+ PATTERN
+
def on_send(node)
+ offense_for_matcher(node) || offense_for_response_status(node)
+ end
+
+ def autocorrect(node)
+ lambda do |corrector|
+ replacement = replace_matcher(node) || replace_response_status(node)
+ corrector.replace(node.source_range, replacement)
+ end
+ end
+
+ private
+
+ def offense_for_matcher(node)
return unless have_http_status?(node)
offenses = [
@@ -57,16 +85,31 @@ module RuboCop
return if offenses.empty?
- add_offense(node, message: message_for(offenses))
+ add_offense(node, message: message_for(*offenses))
end
- def autocorrect(node)
- lambda do |corrector|
- corrector.replace(node.source_range, replacement(node))
- end
+ def offense_for_response_status(node)
+ return unless response_status_eq?(node)
+
+ add_offense(node, message: message_for(MSG_RESPONSE_STATUS))
end
- private
+ def replace_matcher(node)
+ return unless have_http_status?(node)
+
+ code = extract_numeric_code(node)
+ arg = code_to_symbol(code) || argument(node).source
+
+ format(REPLACEMENT, arg: arg)
+ end
+
+ def replace_response_status(node)
+ expectation, code = response_status_eq?(node)
+ return unless code
+
+ arg = code_to_symbol(code)
+ format(REPLACEMENT_RESPONSE_STATUS, expectation: expectation, arg: arg)
+ end
def offense_for_name(node)
return if method_name(node) == :have_gitlab_http_status
@@ -79,22 +122,15 @@ module RuboCop
return unless code
symbol = code_to_symbol(code)
- return format(MSG_UNKNOWN, code: code) unless symbol
+ return format(MSG_UNKNOWN_STATUS, code: code) unless symbol
- format(MSG_STATUS, name: symbol, code: code)
+ format(MSG_NUMERIC_STATUS, name: symbol, code: code)
end
- def message_for(offenses)
+ def message_for(*offenses)
(offenses + [MSG_DOCS_LINK]).join(' ')
end
- def replacement(node)
- code = extract_numeric_code(node)
- arg = code_to_symbol(code) || argument(node).source
-
- format(REPLACEMENT, arg: arg)
- end
-
def code_to_symbol(code)
CODE_TO_SYMBOL[code]&.inspect
end