bettery 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/.yardopts +5 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/bettery.gemspec +26 -0
- data/lib/bettery.rb +28 -0
- data/lib/bettery/client.rb +170 -0
- data/lib/bettery/client/projects.rb +45 -0
- data/lib/bettery/configurable.rb +41 -0
- data/lib/bettery/default.rb +92 -0
- data/lib/bettery/error.rb +115 -0
- data/lib/bettery/project.rb +45 -0
- data/lib/bettery/response/raise_error.rb +21 -0
- data/lib/bettery/version.rb +3 -0
- data/spec/bettery/client/projects_spec.rb +38 -0
- data/spec/bettery/client_spec.rb +307 -0
- data/spec/bettery/project_spec.rb +51 -0
- data/spec/bettery_spec.rb +51 -0
- data/spec/cassettes/Bettery_Client/_get/handles_query_params.json +1 -0
- data/spec/cassettes/Bettery_Client/_head/handles_query_params.json +1 -0
- data/spec/cassettes/Bettery_Client/_last_response/caches_the_last_agent_response.json +1 -0
- data/spec/cassettes/Bettery_Client_Projects/_project/returns_the_matching_project.json +1 -0
- data/spec/cassettes/Bettery_Client_Projects/_project_/returns_false_if_the_project_doesn_t_exist.json +1 -0
- data/spec/cassettes/Bettery_Client_Projects/_project_/returns_true_if_the_project_exists.json +1 -0
- data/spec/cassettes/Bettery_Client_Projects/_projects/returns_projects_on_betterplace.json +1 -0
- data/spec/spec_helper.rb +84 -0
- data/yard/default/fulldoc/html/css/common.css +3 -0
- data/yard/default/layout/html/setup.rb +17 -0
- metadata +117 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'bettery/response/raise_error'
|
2
|
+
require 'bettery/version'
|
3
|
+
|
4
|
+
module Bettery
|
5
|
+
|
6
|
+
# Default configuration options for {Client}
|
7
|
+
module Default
|
8
|
+
|
9
|
+
# Default API endpoint
|
10
|
+
API_BASE_ENDPOINT = "https://api.betterplace.org"
|
11
|
+
|
12
|
+
# Default User Agent header string
|
13
|
+
USER_AGENT = "Bettery Ruby Gem #{Bettery::VERSION}"
|
14
|
+
|
15
|
+
# Default media type
|
16
|
+
MEDIA_TYPE = "application/json"
|
17
|
+
|
18
|
+
# Default localization
|
19
|
+
LOCALE = "de"
|
20
|
+
|
21
|
+
# Default Faraday middleware stack
|
22
|
+
MIDDLEWARE = Faraday::RackBuilder.new do |builder|
|
23
|
+
builder.use Bettery::Response::RaiseError
|
24
|
+
builder.adapter Faraday.default_adapter
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
|
29
|
+
# Configuration options
|
30
|
+
# @return [Hash]
|
31
|
+
def options
|
32
|
+
Hash[Bettery::Configurable.keys.map{|key| [key, send(key)]}]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Default locale from ENV or {LOCALE}
|
36
|
+
# @return [String]
|
37
|
+
def locale
|
38
|
+
ENV['BETTERY_LOCALE'] || LOCALE
|
39
|
+
end
|
40
|
+
|
41
|
+
# Default API base endpoint from ENV or {API_BASE_ENDPOINT}
|
42
|
+
# @return [String]
|
43
|
+
def api_base_endpoint
|
44
|
+
ENV['BETTERY_API_BASE_ENDPOINT'] || API_BASE_ENDPOINT
|
45
|
+
end
|
46
|
+
|
47
|
+
# Default options for Faraday::Connection
|
48
|
+
# @return [Hash]
|
49
|
+
def connection_options
|
50
|
+
{
|
51
|
+
headers: {
|
52
|
+
accept: default_media_type,
|
53
|
+
user_agent: user_agent
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
# Default media type from ENV or {MEDIA_TYPE}
|
59
|
+
# @return [String]
|
60
|
+
def default_media_type
|
61
|
+
ENV['BETTERY_DEFAULT_MEDIA_TYPE'] || MEDIA_TYPE
|
62
|
+
end
|
63
|
+
|
64
|
+
# Default middleware stack for Faraday::Connection
|
65
|
+
# from {MIDDLEWARE}
|
66
|
+
# @return [String]
|
67
|
+
def middleware
|
68
|
+
MIDDLEWARE
|
69
|
+
end
|
70
|
+
|
71
|
+
# Default pagination page size from ENV
|
72
|
+
# @return [Fixnum] Page size
|
73
|
+
def per_page
|
74
|
+
page_size = ENV['BETTERY_PER_PAGE']
|
75
|
+
|
76
|
+
page_size.to_i if page_size
|
77
|
+
end
|
78
|
+
|
79
|
+
# Default proxy server URI for Faraday connection from ENV
|
80
|
+
# @return [String]
|
81
|
+
def proxy
|
82
|
+
ENV['BETTERY_PROXY']
|
83
|
+
end
|
84
|
+
|
85
|
+
# Default User-Agent header string from ENV or {USER_AGENT}
|
86
|
+
# @return [String]
|
87
|
+
def user_agent
|
88
|
+
ENV['BETTERY_USER_AGENT'] || USER_AGENT
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Bettery
|
2
|
+
# Custom error class for rescuing from all Betterplace errors
|
3
|
+
class Error < StandardError
|
4
|
+
|
5
|
+
# Returns the appropriate Bettery::Error sublcass based
|
6
|
+
# on status and response message
|
7
|
+
#
|
8
|
+
# @param [Hash] response HTTP response
|
9
|
+
# @return [Bettery::Error]
|
10
|
+
def self.from_response(response)
|
11
|
+
status = response[:status].to_i
|
12
|
+
body = response[:body].to_s
|
13
|
+
headers = response[:response_headers]
|
14
|
+
|
15
|
+
if klass = case status
|
16
|
+
when 400 then Bettery::BadRequest
|
17
|
+
when 403 then Bettery::Forbidden
|
18
|
+
when 404 then Bettery::NotFound
|
19
|
+
when 400..499 then Bettery::ClientError
|
20
|
+
when 500 then Bettery::InternalServerError
|
21
|
+
when 502 then Bettery::BadGateway
|
22
|
+
when 503 then Bettery::ServiceUnavailable
|
23
|
+
when 500..599 then Bettery::ServerError
|
24
|
+
end
|
25
|
+
klass.new(response)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(response=nil)
|
30
|
+
@response = response
|
31
|
+
super(build_error_message)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def data
|
37
|
+
@data ||=
|
38
|
+
if (body = @response[:body]) && !body.empty?
|
39
|
+
if body.is_a?(String) &&
|
40
|
+
@response[:response_headers] &&
|
41
|
+
@response[:response_headers][:content_type] =~ /json/
|
42
|
+
|
43
|
+
Sawyer::Agent.serializer.decode(body)
|
44
|
+
else
|
45
|
+
body
|
46
|
+
end
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def response_message
|
53
|
+
case data
|
54
|
+
when Hash
|
55
|
+
data[:message]
|
56
|
+
when String
|
57
|
+
data
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def response_error_name
|
62
|
+
"Error: #{data[:name]}" if data.is_a?(Hash) && data[:name]
|
63
|
+
end
|
64
|
+
|
65
|
+
def response_error_reason
|
66
|
+
data[:reason] if data.is_a?(Hash) && data[:reason]
|
67
|
+
end
|
68
|
+
|
69
|
+
def response_error_backtrace
|
70
|
+
return nil unless data.is_a?(Hash) && !Array(data[:backtrace]).empty?
|
71
|
+
|
72
|
+
summary = "\nError backtrace:\n"
|
73
|
+
summary << data[:backtrace].join("\n")
|
74
|
+
|
75
|
+
summary
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_error_message
|
79
|
+
return nil if @response.nil?
|
80
|
+
|
81
|
+
message = "#{@response[:method].to_s.upcase} "
|
82
|
+
message << "#{@response[:url]}: "
|
83
|
+
message << "#{@response[:status]} - "
|
84
|
+
message << "#{response_error_name}\n" unless response_error_name.nil?
|
85
|
+
message << "#{response_error_reason}\n" unless response_error_reason.nil?
|
86
|
+
message << "#{response_message}\n" unless response_message.nil?
|
87
|
+
message << "#{response_error_backtrace}" unless response_error_backtrace.nil?
|
88
|
+
message
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Raised on errors in the 400-499 range
|
93
|
+
class ClientError < Error; end
|
94
|
+
|
95
|
+
# Raised when Betterplace returns a 400 HTTP status code
|
96
|
+
class BadRequest < ClientError; end
|
97
|
+
|
98
|
+
# Raised when Betterplace returns a 403 HTTP status code
|
99
|
+
class Forbidden < ClientError; end
|
100
|
+
|
101
|
+
# Raised when Betterplace returns a 404 HTTP status code
|
102
|
+
class NotFound < ClientError; end
|
103
|
+
|
104
|
+
# Raised on errors in the 500-599 range
|
105
|
+
class ServerError < Error; end
|
106
|
+
|
107
|
+
# Raised when Betterplace returns a 500 HTTP status code
|
108
|
+
class InternalServerError < ServerError; end
|
109
|
+
|
110
|
+
# Raised when Betterplace returns a 502 HTTP status code
|
111
|
+
class BadGateway < ServerError; end
|
112
|
+
|
113
|
+
# Raised when Betterplace returns a 503 HTTP status code
|
114
|
+
class ServiceUnavailable < ServerError; end
|
115
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Bettery
|
2
|
+
class Project
|
3
|
+
attr_accessor :id
|
4
|
+
REGEXP = /\Ahttps?.+\/projects\/(?<id>\d+).*\z/
|
5
|
+
|
6
|
+
def initialize(project)
|
7
|
+
case project
|
8
|
+
when Integer
|
9
|
+
@id = project
|
10
|
+
when String
|
11
|
+
@id = extract_id_from_url(project)
|
12
|
+
when Project
|
13
|
+
@id = project.id
|
14
|
+
when Hash
|
15
|
+
@id = project[:id]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String] Project API path
|
20
|
+
def path
|
21
|
+
"projects/#{id}.json"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get the api path for a project
|
25
|
+
# @param project [Integer, String, Hash, Project] A Betterplace project.
|
26
|
+
# @return [String] Api path.
|
27
|
+
def self.path project
|
28
|
+
new(project).path
|
29
|
+
end
|
30
|
+
|
31
|
+
# Project URL based on {Bettery::Client#api_endpoint}
|
32
|
+
# @return [String]
|
33
|
+
def url
|
34
|
+
File.join(Bettery.api_endpoint, path)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def extract_id_from_url(url)
|
40
|
+
if match = REGEXP.match(url)
|
41
|
+
match[:id].to_i
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'bettery/error'
|
3
|
+
|
4
|
+
module Bettery
|
5
|
+
# Faraday response middleware
|
6
|
+
module Response
|
7
|
+
|
8
|
+
# This class raises an Bettery-flavored exception based
|
9
|
+
# HTTP status codes returned by the API
|
10
|
+
class RaiseError < Faraday::Response::Middleware
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def on_complete(response)
|
15
|
+
if error = Bettery::Error.from_response(response)
|
16
|
+
raise error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bettery::Client::Projects do
|
4
|
+
before do
|
5
|
+
Bettery.reset!
|
6
|
+
@client = bettery_client
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".project", :vcr do
|
10
|
+
it "returns the matching project" do
|
11
|
+
project = @client.project(12345)
|
12
|
+
expect(project.id).to eq(12345)
|
13
|
+
expect(project.title).to eq("Finanzierung der Nachsorge")
|
14
|
+
assert_requested :get, betterplace_url("/projects/12345.json")
|
15
|
+
end
|
16
|
+
end # .project
|
17
|
+
|
18
|
+
describe ".projects", :vcr do
|
19
|
+
it "returns projects on betterplace" do
|
20
|
+
projects = Bettery.projects
|
21
|
+
expect(projects.data).to be_kind_of Array
|
22
|
+
assert_requested :get, betterplace_url("/projects.json")
|
23
|
+
end
|
24
|
+
end # .projects
|
25
|
+
|
26
|
+
describe ".project?", :vcr do
|
27
|
+
it "returns true if the project exists" do
|
28
|
+
result = @client.project?(12345)
|
29
|
+
expect(result).to be true
|
30
|
+
assert_requested :get, betterplace_url("/projects/12345.json")
|
31
|
+
end
|
32
|
+
it "returns false if the project doesn't exist" do
|
33
|
+
result = @client.project?(112233445566778899)
|
34
|
+
expect(result).to be false
|
35
|
+
assert_requested :get, betterplace_url("/projects/112233445566778899.json")
|
36
|
+
end
|
37
|
+
end # .project?
|
38
|
+
end
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe Bettery::Client do
|
5
|
+
before do
|
6
|
+
Bettery.reset!
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
Bettery.reset!
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "module configuration" do
|
14
|
+
before do
|
15
|
+
Bettery.reset!
|
16
|
+
Bettery.configure do |config|
|
17
|
+
Bettery::Configurable.keys.each do |key|
|
18
|
+
config.send("#{key}=", "Some #{key}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
Bettery.reset!
|
25
|
+
end
|
26
|
+
|
27
|
+
it "inherits the module configuration" do
|
28
|
+
client = Bettery::Client.new
|
29
|
+
Bettery::Configurable.keys.each do |key|
|
30
|
+
expect(client.instance_variable_get(:"@#{key}")).to eq("Some #{key}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "with class level configuration" do
|
35
|
+
before do
|
36
|
+
@opts = {
|
37
|
+
connection_options: {ssl: {verify: false}},
|
38
|
+
per_page: 40
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "overrides module configuration" do
|
43
|
+
client = Bettery::Client.new(@opts)
|
44
|
+
expect(client.per_page).to eq(40)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "can set configuration after initialization" do
|
48
|
+
client = Bettery::Client.new
|
49
|
+
client.configure do |config|
|
50
|
+
@opts.each do |key, value|
|
51
|
+
config.send("#{key}=", value)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe ".agent" do
|
59
|
+
before do
|
60
|
+
Bettery.reset!
|
61
|
+
end
|
62
|
+
|
63
|
+
it "acts like a Sawyer agent" do
|
64
|
+
expect(Bettery.client.agent).to respond_to :start
|
65
|
+
end
|
66
|
+
|
67
|
+
it "caches the agent" do
|
68
|
+
agent = Bettery.client.agent
|
69
|
+
expect(agent.object_id).to eq(Bettery.client.agent.object_id)
|
70
|
+
end
|
71
|
+
end # .agent
|
72
|
+
|
73
|
+
describe ".last_response", :vcr do
|
74
|
+
it "caches the last agent response" do
|
75
|
+
Bettery.reset!
|
76
|
+
client = Bettery.client
|
77
|
+
expect(client.last_response).to be_nil
|
78
|
+
client.get "projects.json"
|
79
|
+
expect(client.last_response.status).to eq(200)
|
80
|
+
end
|
81
|
+
end # .last_response
|
82
|
+
|
83
|
+
describe ".get", :vcr do
|
84
|
+
before(:each) do
|
85
|
+
Bettery.reset!
|
86
|
+
end
|
87
|
+
|
88
|
+
it "handles query params" do
|
89
|
+
Bettery.get "projects.json", foo: "bar"
|
90
|
+
assert_requested :get, "https://api.betterplace.org/de/api_v4/projects.json?foo=bar"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "handles headers" do
|
94
|
+
request = stub_get("zen").
|
95
|
+
with(query: {foo: "bar"}, headers: {accept: "text/plain"})
|
96
|
+
Bettery.get "zen", foo: "bar", accept: "text/plain"
|
97
|
+
assert_requested request
|
98
|
+
end
|
99
|
+
end # .get
|
100
|
+
|
101
|
+
describe ".head", :vcr do
|
102
|
+
it "handles query params" do
|
103
|
+
Bettery.reset!
|
104
|
+
Bettery.head "projects.json", foo: "bar"
|
105
|
+
assert_requested :head, "https://api.betterplace.org/de/api_v4/projects.json?foo=bar"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "handles headers" do
|
109
|
+
Bettery.reset!
|
110
|
+
request = stub_head("projects.json").
|
111
|
+
with(query: {foo: "bar"}, headers: {accept: "text/plain"})
|
112
|
+
Bettery.head "projects.json", foo: "bar", accept: "text/plain"
|
113
|
+
assert_requested request
|
114
|
+
end
|
115
|
+
end # .head
|
116
|
+
|
117
|
+
describe "when making requests" do
|
118
|
+
before do
|
119
|
+
Bettery.reset!
|
120
|
+
@client = Bettery.client
|
121
|
+
end
|
122
|
+
|
123
|
+
it "Accepts application/json by default" do
|
124
|
+
VCR.use_cassette 'projects' do
|
125
|
+
request = stub_get("projects.json").
|
126
|
+
with(headers: {accept: "application/json"})
|
127
|
+
@client.get "projects.json"
|
128
|
+
assert_requested request
|
129
|
+
expect(@client.last_response.status).to eq(200)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
it "allows Accept'ing another media type" do
|
134
|
+
request = stub_get("projects.json").
|
135
|
+
with(headers: {accept: "application/vnd.betterplace.beta.diff+json"})
|
136
|
+
@client.get "projects.json", accept: "application/vnd.betterplace.beta.diff+json"
|
137
|
+
assert_requested request
|
138
|
+
expect(@client.last_response.status).to eq(200)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "sets a default user agent" do
|
142
|
+
request = stub_get("projects.json").
|
143
|
+
with(headers: {user_agent: Bettery::Default.user_agent})
|
144
|
+
@client.get "projects.json"
|
145
|
+
assert_requested request
|
146
|
+
expect(@client.last_response.status).to eq(200)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "sets a custom user agent" do
|
150
|
+
user_agent = "Mozilla/5.0 I am Spartacus!"
|
151
|
+
request = stub_get("projects.json").
|
152
|
+
with(headers: {user_agent: user_agent})
|
153
|
+
client = Bettery::Client.new(user_agent: user_agent)
|
154
|
+
client.get "projects.json"
|
155
|
+
assert_requested request
|
156
|
+
expect(client.last_response.status).to eq(200)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "sets a proxy server" do
|
160
|
+
Bettery.configure do |config|
|
161
|
+
config.proxy = 'http://proxy.example.com:80'
|
162
|
+
end
|
163
|
+
conn = Bettery.client.send(:agent).instance_variable_get(:"@conn")
|
164
|
+
expect(conn.proxy[:uri].to_s).to eq('http://proxy.example.com')
|
165
|
+
end
|
166
|
+
|
167
|
+
it "passes along request headers for POST" do
|
168
|
+
headers = {"X-Betterplace-Foo" => "bar"}
|
169
|
+
request = stub_post("projects.json").
|
170
|
+
with(headers: headers).
|
171
|
+
to_return(status: 201)
|
172
|
+
client = Bettery::Client.new
|
173
|
+
client.post "projects.json", headers: headers
|
174
|
+
assert_requested request
|
175
|
+
expect(client.last_response.status).to eq(201)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "error handling" do
|
180
|
+
before do
|
181
|
+
Bettery.reset!
|
182
|
+
VCR.turn_off!
|
183
|
+
end
|
184
|
+
|
185
|
+
after do
|
186
|
+
VCR.turn_on!
|
187
|
+
end
|
188
|
+
|
189
|
+
it "raises on 404" do
|
190
|
+
stub_get('booya').to_return(status: 404)
|
191
|
+
expect { Bettery.get('booya') }.to raise_error Bettery::NotFound
|
192
|
+
end
|
193
|
+
|
194
|
+
it "raises on 500" do
|
195
|
+
stub_get('boom').to_return(status: 500)
|
196
|
+
expect { Bettery.get('boom') }.to raise_error Bettery::InternalServerError
|
197
|
+
end
|
198
|
+
|
199
|
+
it "includes a message" do
|
200
|
+
stub_get('boom').
|
201
|
+
to_return \
|
202
|
+
status: 404,
|
203
|
+
headers: {
|
204
|
+
content_type: "application/json",
|
205
|
+
},
|
206
|
+
body: {message: "Couldn't find Project with id=boom"}.to_json
|
207
|
+
begin
|
208
|
+
Bettery.get('boom')
|
209
|
+
rescue Bettery::NotFound => e
|
210
|
+
expect(e.message).to include("GET https://api.betterplace.org/de/api_v4/boom: 404 - Couldn't find Project with id=boom")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
it "includes all error info" do
|
215
|
+
stub_get('boom').
|
216
|
+
to_return \
|
217
|
+
status: 404,
|
218
|
+
headers: {
|
219
|
+
content_type: "application/json",
|
220
|
+
},
|
221
|
+
body: {
|
222
|
+
name: "GeneralError",
|
223
|
+
reason: "Record Not Found",
|
224
|
+
backtrace: [
|
225
|
+
"/path/to/file:23:in `method'",
|
226
|
+
"/path/to/file:42:in `method2'"
|
227
|
+
],
|
228
|
+
message: "Couldn't find Project with id=666"
|
229
|
+
}.to_json
|
230
|
+
begin
|
231
|
+
Bettery.get('boom')
|
232
|
+
rescue Bettery::NotFound => e
|
233
|
+
expect(e.message).to include("GET https://api.betterplace.org/de/api_v4/boom: 404 - Error: GeneralError")
|
234
|
+
expect(e.message).to include("Record Not Found")
|
235
|
+
expect(e.message).to include("Couldn't find Project with id=666")
|
236
|
+
expect(e.message).to include("/path/to/file:23:in `method'")
|
237
|
+
expect(e.message).to include("/path/to/file:42:in `method2'")
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
it "raises Forbidden on 403" do
|
242
|
+
stub_get('some/admin/stuffs').to_return(status: 403)
|
243
|
+
expect { Bettery.get('some/admin/stuffs') }.to raise_error Bettery::Forbidden
|
244
|
+
end
|
245
|
+
|
246
|
+
it "handle an error with a text body" do
|
247
|
+
stub_get('boom').to_return \
|
248
|
+
status: 400,
|
249
|
+
body: "Client error"
|
250
|
+
begin
|
251
|
+
Bettery.get('boom')
|
252
|
+
rescue Bettery::BadRequest => e
|
253
|
+
expect(e.message).to include("Client error")
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
it "raises on unknown client errors" do
|
258
|
+
stub_get('user').to_return \
|
259
|
+
status: 418,
|
260
|
+
headers: {
|
261
|
+
content_type: "application/json",
|
262
|
+
},
|
263
|
+
body: {message: "I'm a teapot"}.to_json
|
264
|
+
expect { Bettery.get('user') }.to raise_error Bettery::ClientError
|
265
|
+
end
|
266
|
+
|
267
|
+
it "raises on unknown server errors" do
|
268
|
+
stub_get('user').to_return \
|
269
|
+
status: 509,
|
270
|
+
headers: {
|
271
|
+
content_type: "application/json",
|
272
|
+
},
|
273
|
+
body: {message: "Bandwidth exceeded"}.to_json
|
274
|
+
expect { Bettery.get('user') }.to raise_error Bettery::ServerError
|
275
|
+
end
|
276
|
+
|
277
|
+
it "raises Bettery::BadGateway on 502 server errors" do
|
278
|
+
stub_get('user').to_return \
|
279
|
+
status: 502,
|
280
|
+
headers: {
|
281
|
+
content_type: "application/json",
|
282
|
+
},
|
283
|
+
body: {message: "BadGateway"}.to_json
|
284
|
+
expect { Bettery.get('user') }.to raise_error Bettery::BadGateway
|
285
|
+
end
|
286
|
+
|
287
|
+
it "raises Bettery::ServiceUnavailable on 503 server errors" do
|
288
|
+
stub_get('user').to_return \
|
289
|
+
status: 503,
|
290
|
+
headers: {
|
291
|
+
content_type: "application/json",
|
292
|
+
},
|
293
|
+
body: {message: "Service Unavailable"}.to_json
|
294
|
+
expect { Bettery.get('user') }.to raise_error Bettery::ServiceUnavailable
|
295
|
+
end
|
296
|
+
|
297
|
+
it "handles an error response with an array body" do
|
298
|
+
stub_get('user').to_return \
|
299
|
+
status: 500,
|
300
|
+
headers: {
|
301
|
+
content_type: "application/json"
|
302
|
+
},
|
303
|
+
body: [].to_json
|
304
|
+
expect { Bettery.get('user') }.to raise_error Bettery::ServerError
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|