This repository has been archived by the owner on Aug 14, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add more specific error classes access the entire response from the error object access the error descriptions directly from the error object
- Loading branch information
Jannik Graw
committed
Jan 14, 2016
1 parent
ba7d811
commit ebe97fd
Showing
7 changed files
with
236 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
module Shipcloud | ||
class ShipcloudError < StandardError | ||
attr_reader :errors, :response | ||
|
||
def initialize(response = nil) | ||
@response = response | ||
@errors = parse_errors | ||
error_message = errors.empty? ? response_body : errors | ||
super(error_message) | ||
end | ||
|
||
# Returns the appropriate Shipcloud::ShipcloudError subclass based | ||
# on status code | ||
# | ||
# @param [HTTPResponse] response HTTP response | ||
# @return [Shipcloud::ShipcloudError] | ||
def self.from_response(response) | ||
response_code = response.code.to_i | ||
if error_class = error_class_for(response_code) | ||
error_class.new(response) | ||
end | ||
end | ||
|
||
private | ||
|
||
def self.error_class_for(response_code) | ||
case response_code | ||
when 400 then InvalidRequestError | ||
when 401 then AuthenticationError | ||
when 402 then TooManyRequests | ||
when 404 then NotFoundError | ||
when 400..499 then ClientError | ||
when 500..599 then ServerError | ||
end | ||
end | ||
|
||
def parse_errors | ||
return [] unless response_body | ||
data = JSON.parse(response_body) | ||
if data.is_a?(Hash) && data["errors"] | ||
data["errors"] | ||
else | ||
[] | ||
end | ||
rescue JSON::ParserError | ||
[] | ||
end | ||
|
||
def response_body | ||
return unless @response | ||
@response.body | ||
end | ||
end | ||
|
||
# Raised on errors in the 400-499 range | ||
class ClientError < ShipcloudError; end | ||
class AuthenticationError < ClientError; end | ||
class InvalidRequestError < ClientError; end | ||
class TooManyRequests < ClientError; end | ||
class NotFoundError < ClientError; end | ||
|
||
# Raised on errors in the 500-599 range | ||
class ServerError < ShipcloudError; end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
require "spec_helper" | ||
|
||
describe Shipcloud::ShipcloudError do | ||
describe ".from_response" do | ||
context "with a response with status code 400" do | ||
it "returns a Shipcloud::InvalidRequestError" do | ||
expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 400))).to be_a( | ||
Shipcloud::InvalidRequestError | ||
) | ||
end | ||
end | ||
|
||
context "with a response with status code 401" do | ||
it "returns a Shipcloud::AuthenticationError" do | ||
expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 401))).to be_a( | ||
Shipcloud::AuthenticationError | ||
) | ||
end | ||
end | ||
|
||
context "with a response with status code 402" do | ||
it "returns a Shipcloud::TooManyRequests" do | ||
expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 402))).to be_a( | ||
Shipcloud::TooManyRequests | ||
) | ||
end | ||
end | ||
|
||
context "with a response with status code 404" do | ||
it "returns a Shipcloud::NotFoundError" do | ||
expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 404))).to be_a( | ||
Shipcloud::NotFoundError | ||
) | ||
end | ||
end | ||
|
||
context "with a response with a 4xx status code" do | ||
it "returns a Shipcloud::ClientError" do | ||
expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 400))).to be_a( | ||
Shipcloud::ClientError | ||
) | ||
end | ||
end | ||
|
||
context "with a response with a 5xx status code" do | ||
it "returns a Shipcloud::ClientError" do | ||
expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 500))).to be_a( | ||
Shipcloud::ServerError | ||
) | ||
end | ||
end | ||
|
||
context "with a 200 response" do | ||
it "returns nil" do | ||
expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 200))).to be_nil | ||
end | ||
end | ||
end | ||
|
||
describe "#message" do | ||
context "with an errors node in the response body" do | ||
it "returns the errors formated as one string" do | ||
errors = ["error 1", "error 2"] | ||
response = build_response(body: { errors: errors }.to_json) | ||
error = Shipcloud::ShipcloudError.new(response) | ||
|
||
expect(error.message).to eq '["error 1", "error 2"]' | ||
end | ||
end | ||
context "without an errors node in the response body" do | ||
it "returns the body of the response" do | ||
error = Shipcloud::ShipcloudError.new(build_response(body: "test")) | ||
|
||
expect(error.message).to eq "test" | ||
end | ||
end | ||
end | ||
|
||
describe "#errors" do | ||
it "returns the errors node of the response" do | ||
errors = ["error 1", "error 2"] | ||
response = build_response(body: { errors: errors }.to_json) | ||
error = Shipcloud::ShipcloudError.new(response) | ||
|
||
expect(error.errors).to eq errors | ||
end | ||
context "with a response that has no errors node" do | ||
it "returns an empty list" do | ||
response = build_response(body: {}.to_json) | ||
error = Shipcloud::ShipcloudError.new(response) | ||
|
||
expect(error.errors).to eq [] | ||
end | ||
end | ||
context "with a response that has no JSON formated body" do | ||
it "returns an empty list" do | ||
response = build_response(body: "error") | ||
error = Shipcloud::ShipcloudError.new(response) | ||
|
||
expect(error.errors).to eq [] | ||
end | ||
end | ||
end | ||
|
||
describe "#response" do | ||
it "returns the response" do | ||
response = build_response | ||
error = Shipcloud::ShipcloudError.new(response) | ||
|
||
expect(error.response).to eq response | ||
end | ||
end | ||
|
||
def build_response(status_code: 400, body: nil) | ||
double(code: status_code.to_s, body: body) | ||
end | ||
end |