chassis 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +362 -0
  6. data/Rakefile +33 -0
  7. data/chassis.gemspec +41 -0
  8. data/examples/repo.rb +40 -0
  9. data/lib/chassis.rb +81 -0
  10. data/lib/chassis/array_utils.rb +8 -0
  11. data/lib/chassis/circuit_panel.rb +22 -0
  12. data/lib/chassis/core_ext/array.rb +5 -0
  13. data/lib/chassis/core_ext/hash.rb +5 -0
  14. data/lib/chassis/core_ext/string.rb +13 -0
  15. data/lib/chassis/delegate.rb +29 -0
  16. data/lib/chassis/dirty_session.rb +105 -0
  17. data/lib/chassis/error.rb +7 -0
  18. data/lib/chassis/faraday.rb +226 -0
  19. data/lib/chassis/form.rb +56 -0
  20. data/lib/chassis/hash_utils.rb +16 -0
  21. data/lib/chassis/heroku.rb +5 -0
  22. data/lib/chassis/initializable.rb +11 -0
  23. data/lib/chassis/logger.rb +8 -0
  24. data/lib/chassis/observable.rb +19 -0
  25. data/lib/chassis/persistence.rb +49 -0
  26. data/lib/chassis/rack/bouncer.rb +33 -0
  27. data/lib/chassis/rack/builder_shim_patch.rb +7 -0
  28. data/lib/chassis/rack/health_check.rb +45 -0
  29. data/lib/chassis/rack/instrumentation.rb +20 -0
  30. data/lib/chassis/rack/json_body_parser.rb +20 -0
  31. data/lib/chassis/rack/no_robots.rb +24 -0
  32. data/lib/chassis/registry.rb +30 -0
  33. data/lib/chassis/repo.rb +73 -0
  34. data/lib/chassis/repo/base_repo.rb +99 -0
  35. data/lib/chassis/repo/delegation.rb +78 -0
  36. data/lib/chassis/repo/lazy_association.rb +57 -0
  37. data/lib/chassis/repo/memory_repo.rb +7 -0
  38. data/lib/chassis/repo/null_repo.rb +64 -0
  39. data/lib/chassis/repo/pstore_repo.rb +54 -0
  40. data/lib/chassis/repo/record_map.rb +44 -0
  41. data/lib/chassis/repo/redis_repo.rb +55 -0
  42. data/lib/chassis/serializable.rb +52 -0
  43. data/lib/chassis/string_utils.rb +50 -0
  44. data/lib/chassis/version.rb +3 -0
  45. data/lib/chassis/web_service.rb +61 -0
  46. data/test/array_utils_test.rb +23 -0
  47. data/test/chassis_test.rb +7 -0
  48. data/test/circuit_panel_test.rb +22 -0
  49. data/test/core_ext/array_test.rb +8 -0
  50. data/test/core_ext/hash_test.rb +8 -0
  51. data/test/core_ext/string_test.rb +16 -0
  52. data/test/delegate_test.rb +41 -0
  53. data/test/dirty_session_test.rb +138 -0
  54. data/test/error_test.rb +12 -0
  55. data/test/faraday_test.rb +749 -0
  56. data/test/form_test.rb +29 -0
  57. data/test/hash_utils_test.rb +17 -0
  58. data/test/initializable_test.rb +22 -0
  59. data/test/logger_test.rb +43 -0
  60. data/test/observable_test.rb +27 -0
  61. data/test/persistence_test.rb +112 -0
  62. data/test/prox_test.rb +7 -0
  63. data/test/rack/bouncer_test.rb +42 -0
  64. data/test/rack/builder_patch_test.rb +36 -0
  65. data/test/rack/health_check_test.rb +35 -0
  66. data/test/rack/instrumentation_test.rb +38 -0
  67. data/test/rack/json_body_parser_test.rb +38 -0
  68. data/test/rack/no_robots_test.rb +34 -0
  69. data/test/registry_test.rb +26 -0
  70. data/test/repo/delegation_test.rb +101 -0
  71. data/test/repo/lazy_association_test.rb +115 -0
  72. data/test/repo/memory_repo_test.rb +25 -0
  73. data/test/repo/null_repo_test.rb +48 -0
  74. data/test/repo/pstore_repo_test.rb +28 -0
  75. data/test/repo/redis_repo_test.rb +26 -0
  76. data/test/repo/repo_tests.rb +120 -0
  77. data/test/repo_test.rb +76 -0
  78. data/test/serializable_test.rb +77 -0
  79. data/test/string_utils_test.rb +21 -0
  80. data/test/test_helper.rb +10 -0
  81. data/test/web_service_test.rb +107 -0
  82. metadata +426 -0
@@ -0,0 +1,3 @@
1
+ module Chassis
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,61 @@
1
+ require 'sinatra'
2
+ require 'sinatra/json'
3
+ require 'rack/contrib/bounce_favicon'
4
+ require 'rack/deflater'
5
+
6
+ module Chassis
7
+ class WebService < Sinatra::Base
8
+ ParameterMissingError = Chassis.error do |key|
9
+ %Q{Request did not provide "#{@key}"}
10
+ end
11
+
12
+ helpers do
13
+ def extract!(key)
14
+ value = params.fetch(key.to_s) do
15
+ raise ParameterMissingError, key
16
+ end
17
+
18
+ raise ParameterMissingError, key unless value.is_a?(Hash)
19
+
20
+ value
21
+ end
22
+
23
+ def halt_json_error(code, errors = {})
24
+ json_error env.fetch('sinatra.error'), code, errors
25
+ end
26
+
27
+ def json_error(ex, code, errors = {})
28
+ halt code, { 'Content-Type' => 'application/json' }, JSON.dump({
29
+ error: { message: ex.message }
30
+ }.merge(errors))
31
+ end
32
+ end
33
+
34
+ error ParameterMissingError do
35
+ halt_json_error 400
36
+ end
37
+
38
+ error Chassis::UnknownFormFieldError do
39
+ halt_json_error 400
40
+ end
41
+
42
+ error Chassis::RecordNotFoundError do
43
+ halt_json_error 404
44
+ end
45
+
46
+ use Rack::NoRobots
47
+ use Rack::Bouncer
48
+ use ::Rack::BounceFavicon
49
+ use ::Rack::Deflater
50
+ use Rack::JsonBodyParser
51
+
52
+ set :cors, false
53
+
54
+ class << self
55
+ def setup_default_middleware(builder)
56
+ super
57
+ builder.use Manifold::Middleware if settings.cors?
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ArrayUtilsTest < MiniTest::Unit::TestCase
4
+ def utils
5
+ Chassis::ArrayUtils
6
+ end
7
+
8
+ def test_extract_options_removes_options_hash_if_present
9
+ args = ['foo', { bar: 'baz' }]
10
+ options = utils.extract_options! args
11
+
12
+ assert_equal({ bar: 'baz' }, options)
13
+ assert_equal(%w(foo), args)
14
+ end
15
+
16
+ def test_extract_options_does_nothing_if_no_options
17
+ args = %w(foo)
18
+ options = utils.extract_options! args
19
+
20
+ assert_equal({}, options)
21
+ assert_equal(%w(foo), args)
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ChassisTest < MiniTest::Unit::TestCase
4
+ def test_it_should_define_a_version
5
+ assert Chassis::VERSION
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'test_helper'
2
+
3
+ class CircuitPanelTest < MiniTest::Unit::TestCase
4
+ def test_circuit_method_returns_the_given_circuit
5
+ panel = Chassis.circuit_panel do
6
+ circuit :test, timeout: 10
7
+ end.new
8
+
9
+ circuit = panel.test
10
+ assert_kind_of Breaker::Circuit, circuit
11
+ assert_equal :test, circuit.name
12
+ end
13
+
14
+ def test_options_passed_to_circuit_are_set_on_the_circuit
15
+ panel = Chassis.circuit_panel do
16
+ circuit :test, timeout: 10
17
+ end.new
18
+
19
+ circuit = panel.test
20
+ assert_equal 10, circuit.timeout
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ require_relative '../test_helper'
2
+ require 'chassis/core_ext/array'
3
+
4
+ class ArrayCoreExtTest < MiniTest::Unit::TestCase
5
+ def test_extract_options!
6
+ assert_equal({}, [].extract_options!)
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require_relative '../test_helper'
2
+ require 'chassis/core_ext/hash'
3
+
4
+ class HashCoreExtTest < MiniTest::Unit::TestCase
5
+ def test_symbolize
6
+ assert_equal({ foo: 'bar' }, { 'foo' => 'bar' }.symbolize)
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../test_helper'
2
+ require 'chassis/core_ext/string'
3
+
4
+ class StringCoreExtTest < MiniTest::Unit::TestCase
5
+ def test_underscore
6
+ assert_equal('foo_bar', 'FooBar'.underscore)
7
+ end
8
+
9
+ def test_demodulize
10
+ assert_equal('Bar', 'Foo::Bar'.demodulize)
11
+ end
12
+
13
+ def test_constantize
14
+ assert_equal self.class, self.class.name.constantize
15
+ end
16
+ end
@@ -0,0 +1,41 @@
1
+ require_relative 'test_helper'
2
+
3
+ class DelegateTest < MiniTest::Unit::TestCase
4
+ class Delegator
5
+ include Chassis.delegate(:add, to: :object)
6
+
7
+ attr_reader :object
8
+
9
+ def initialize(object)
10
+ @object = object
11
+ end
12
+ end
13
+
14
+ def test_methods_are_delegated
15
+ delegate = Class.new do
16
+ def add(number)
17
+ number + 5
18
+ end
19
+ end.new
20
+
21
+ delegator = Delegator.new delegate
22
+
23
+ assert_equal 10, delegator.add(5)
24
+ end
25
+
26
+ def test_raises_an_error_if_no_object_to_delegate_to
27
+ delegator = Delegator.new nil
28
+
29
+ assert_raises Chassis::DelegationError do
30
+ delegator.add 1
31
+ end
32
+ end
33
+
34
+ def test_fails_with_an_error_if_nothing_to_delegate_to
35
+ assert_raises ArgumentError do
36
+ Class.new do
37
+ include Chassis.delegate(:foo, :bar)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,138 @@
1
+ require_relative 'test_helper'
2
+
3
+ class DirtySessionTest < MiniTest::Unit::TestCase
4
+ class Person
5
+ include Chassis::Initializable
6
+
7
+ attr_accessor :name, :email, :id
8
+ end
9
+
10
+ attr_reader :person
11
+
12
+ def setup
13
+ @person = Person.new do |person|
14
+ person.name = 'adam'
15
+ person.email = 'example@example.com'
16
+ person.id = 1
17
+ end
18
+ end
19
+
20
+ def test_initialize_as_clean
21
+ session = Chassis::DirtySession.new person
22
+ assert session.clean?
23
+ refute session.dirty?
24
+ end
25
+
26
+ def test_assigning_new_value_marks_the_session_dirty
27
+ session = Chassis::DirtySession.new person
28
+ session.name = 'foo'
29
+
30
+ refute session.clean?
31
+ assert session.dirty?
32
+ end
33
+
34
+ def test_changes_can_be_tested_via_query_method
35
+ session = Chassis::DirtySession.new person
36
+ session.name = 'foo'
37
+
38
+ refute session.clean?
39
+ assert session.dirty?
40
+
41
+ assert_respond_to session, :name_changed?, "Session should respond to changed queries"
42
+ assert session.name_changed?
43
+ end
44
+
45
+ def test_changes_include_all_new_assignments
46
+ session = Chassis::DirtySession.new person
47
+ session.name = 'foo'
48
+
49
+ refute session.clean?
50
+ assert session.dirty?
51
+
52
+ assert_equal(Set.new([:name]), session.changes)
53
+ end
54
+
55
+ def test_changes_are_accessible
56
+ session = Chassis::DirtySession.new person
57
+ session.name = 'foo'
58
+
59
+ refute session.clean?
60
+ assert session.dirty?
61
+
62
+ assert_equal({ name: 'foo' }, session.new_values)
63
+ end
64
+
65
+ def test_assigning_a_new_value_records_the_original_value
66
+ original_name = person.name
67
+ assert original_name, "Precondition: person must have a name"
68
+
69
+ session = Chassis::DirtySession.new person
70
+ session.name = 'foo'
71
+
72
+ refute session.clean?
73
+ assert session.dirty?
74
+
75
+ assert_equal({ name: original_name}, session.original_values)
76
+ end
77
+
78
+ def test_original_values_are_accessible_via_an_original_method
79
+ original_name = person.name
80
+ assert original_name, "Precondition: person must have a name"
81
+
82
+ session = Chassis::DirtySession.new person
83
+ session.name = 'foo'
84
+
85
+ refute session.clean?
86
+ assert session.dirty?
87
+
88
+ assert_respond_to session, :original_name, "Session should respond to original_XXX methods"
89
+ assert_equal original_name, session.original_name
90
+ end
91
+
92
+ def test_assigning_the_same_value_does_not_count_as_a_change
93
+ original_name = person.name
94
+ assert original_name, "Precondition: person must have a name"
95
+
96
+ session = Chassis::DirtySession.new person
97
+ session.name = original_name
98
+
99
+ assert session.clean?, "Setting the same value should not count as a change"
100
+ refute session.dirty?
101
+ end
102
+
103
+ def test_assigning_the_same_value_multiple_times_saves_the_initial_value
104
+ original_name = person.name
105
+ assert original_name, "Precondition: person must have a name"
106
+
107
+ session = Chassis::DirtySession.new person
108
+ session.name = 'matthew'
109
+ session.name = 'michael'
110
+
111
+ refute session.clean?
112
+ assert session.dirty?
113
+
114
+ assert_equal original_name, session.original_name
115
+ end
116
+
117
+ def test_reset_moves_session_to_initial_state
118
+ original_name = person.name
119
+ assert original_name, "Precondition: person must have a name"
120
+
121
+ session = Chassis::DirtySession.new person
122
+ session.name = 'matthew'
123
+
124
+ refute session.clean?
125
+ assert session.dirty?
126
+
127
+ session.reset!
128
+
129
+ assert session.clean?
130
+ refute session.dirty?
131
+
132
+ assert_empty session.changes
133
+ assert_empty session.new_values
134
+ assert_empty session.original_values
135
+
136
+ refute session.name_changed?
137
+ end
138
+ end
@@ -0,0 +1,12 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ErrorTest < MiniTest::Unit::TestCase
4
+ def test_delegates_to_tnt
5
+ klass = Chassis.error do |foo|
6
+ "#{foo} bar"
7
+ end
8
+
9
+ error = klass.new "Adam"
10
+ assert_equal "Adam bar", error.message
11
+ end
12
+ end
@@ -0,0 +1,749 @@
1
+ require_relative "test_helper"
2
+
3
+ class FaradayTest < MiniTest::Unit::TestCase
4
+ def setup
5
+ Harness.config.queue = Harness::SyncQueue.new
6
+ Harness.config.collector = Harness::FakeCollector.new
7
+ end
8
+
9
+ def stats
10
+ Harness.config.collector
11
+ end
12
+
13
+ def build(url = nil, options = {}, &block)
14
+ Faraday.new url, options, &block
15
+ end
16
+
17
+ def test_instruments_all_requests
18
+ faraday = build do |conn|
19
+ conn.request :instrumentation
20
+
21
+ conn.adapter :test do |stub|
22
+ stub.get 'test' do
23
+ [200, {'Content-Type' => 'application/json'}, JSON.dump(foo: 'bar')]
24
+ end
25
+ end
26
+ end
27
+
28
+ faraday.get 'test'
29
+
30
+ refute_empty stats.timers
31
+ timer = stats.timers.first
32
+
33
+ assert_equal 'faraday.get', timer.name
34
+ end
35
+
36
+ def test_instrumentation_namespace_can_be_customized
37
+ faraday = build 'http://example.com' do |conn|
38
+ conn.request :instrumentation, 'http'
39
+
40
+ conn.adapter :test do |stub|
41
+ stub.get 'test' do
42
+ [200, {'Content-Type' => 'application/json'}, JSON.dump(foo: 'bar')]
43
+ end
44
+ end
45
+ end
46
+
47
+ faraday.get 'test'
48
+
49
+ refute_empty stats.timers
50
+ timer = stats.timers.first
51
+
52
+ assert_equal 'http.get', timer.name
53
+ end
54
+
55
+ def test_sends_requests_in_json
56
+ faraday = build do |conn|
57
+ conn.request :encode_json
58
+
59
+ conn.adapter :test do |stub|
60
+ stub.post 'test' do |env|
61
+ json = JSON.load env.fetch(:body)
62
+ [200, {'Content-Type' => 'text/plain'}, json.fetch('foo')]
63
+ end
64
+ end
65
+ end
66
+
67
+ response = faraday.post 'test', foo: 'bar'
68
+
69
+ assert_equal 'bar', response.body
70
+ end
71
+
72
+ def test_parses_json_bodies
73
+ faraday = build do |conn|
74
+ conn.request :encode_json
75
+ conn.response :parse_json
76
+
77
+ conn.adapter :test do |stub|
78
+ stub.post 'test' do |env|
79
+ [ 200,
80
+ {'Requested-Type' => env.fetch(:request_headers).fetch('Content-Type')},
81
+ env.fetch(:body)
82
+ ]
83
+ end
84
+ end
85
+ end
86
+
87
+ response = faraday.post 'test', foo: 'bar'
88
+
89
+ assert_equal(JSON.dump({ 'foo' => 'bar' }), response.body)
90
+ assert_equal 'application/json', response.headers.fetch('Requested-Type')
91
+ end
92
+
93
+ def test_does_not_parse_nil_bodies
94
+ faraday = build do |conn|
95
+ conn.response :parse_json
96
+
97
+ conn.adapter :test do |stub|
98
+ stub.get 'test' do
99
+ [200, {'Content-Type' => 'application/json'}, nil]
100
+ end
101
+ end
102
+ end
103
+
104
+ response = faraday.get 'test'
105
+
106
+ assert_nil response[:body]
107
+ end
108
+
109
+ def test_does_not_parse_empty_bodies
110
+ faraday = build do |conn|
111
+ conn.response :parse_json
112
+
113
+ conn.adapter :test do |stub|
114
+ stub.get 'test' do
115
+ [200, {'Content-Type' => 'application/json'}, '']
116
+ end
117
+ end
118
+ end
119
+
120
+ response = faraday.get 'test'
121
+
122
+ assert_nil response[:body]
123
+ end
124
+
125
+ def test_does_not_parse_empty_strings
126
+ faraday = build do |conn|
127
+ conn.response :parse_json
128
+
129
+ conn.adapter :test do |stub|
130
+ stub.get 'test' do
131
+ [200, {'Content-Type' => 'application/json'}, ' ']
132
+ end
133
+ end
134
+ end
135
+
136
+ response = faraday.get 'test'
137
+
138
+ assert_nil response[:body]
139
+ end
140
+
141
+ def test_does_not_parse_204s
142
+ faraday = build do |conn|
143
+ conn.response :parse_json
144
+
145
+ conn.adapter :test do |stub|
146
+ stub.get 'test' do
147
+ [204, {'Content-Type' => 'application/json'}, '']
148
+ end
149
+ end
150
+ end
151
+
152
+ response = faraday.get 'test'
153
+
154
+ assert_nil response[:body]
155
+ end
156
+
157
+ def test_does_not_parse_304s
158
+ faraday = build do |conn|
159
+ conn.response :parse_json
160
+
161
+ conn.adapter :test do |stub|
162
+ stub.get 'test' do
163
+ [304, {'Content-Type' => 'application/json'}, '']
164
+ end
165
+ end
166
+ end
167
+
168
+ response = faraday.get 'test'
169
+
170
+ assert_nil response[:body]
171
+ end
172
+
173
+ def test_logs_requests
174
+ stream = StringIO.new
175
+ logger = Logger.new stream
176
+ logger.level = :debug
177
+
178
+ faraday = build 'http://example.com' do |conn|
179
+ conn.response :logging, logger
180
+
181
+ conn.adapter :test do |stub|
182
+ stub.get 'test' do
183
+ [200, {}, 'dead']
184
+ end
185
+ end
186
+ end
187
+
188
+ faraday.get 'test', { foo: 'bar' }, { 'This-Header' => 'has_a_value' }
189
+
190
+ stream.rewind ; content = stream.read
191
+
192
+ assert_includes content, 'http://example.com/test'
193
+ assert_includes content, 'This-Header'
194
+ assert_includes content, 'has_a_value'
195
+ assert_includes content, 'foo'
196
+ assert_includes content, 'bar'
197
+ end
198
+
199
+ def test_logs_responses
200
+ stream = StringIO.new
201
+ logger = Logger.new stream
202
+ logger.level = :debug
203
+
204
+ faraday = build 'http://example.com' do |conn|
205
+ conn.response :logging, logger
206
+
207
+ conn.adapter :test do |stub|
208
+ stub.get 'test' do
209
+ [200, {'This-Header' => 'has_a_value'}, 'the_body']
210
+ end
211
+ end
212
+ end
213
+
214
+ faraday.get 'test'
215
+
216
+ stream.rewind ; content = stream.read
217
+
218
+ assert_includes content, '200'
219
+ assert_includes content, 'This-Header'
220
+ assert_includes content, 'has_a_value'
221
+ assert_includes content, 'the_body'
222
+ end
223
+
224
+ def test_raises_a_bad_request_error
225
+ faraday = build do |conn|
226
+ conn.response :server_error_handler
227
+
228
+ conn.adapter :test do |stub|
229
+ stub.get 'test' do
230
+ [400, {}, 'dead']
231
+ end
232
+ end
233
+ end
234
+
235
+ assert_raises Chassis::HttpBadRequestError do
236
+ response = faraday.get 'test'
237
+ end
238
+ end
239
+
240
+ def test_raises_an_unauthorized_error
241
+ faraday = build do |conn|
242
+ conn.response :server_error_handler
243
+
244
+ conn.adapter :test do |stub|
245
+ stub.get 'test' do
246
+ [401, {}, 'dead']
247
+ end
248
+ end
249
+ end
250
+
251
+ assert_raises Chassis::HttpUnauthorizedError do
252
+ response = faraday.get 'test'
253
+ end
254
+ end
255
+
256
+ def test_raises_a_payment_required_error
257
+ faraday = build do |conn|
258
+ conn.response :server_error_handler
259
+ conn.adapter :test do |stub|
260
+ stub.get 'test' do
261
+ [402, {}, 'dead']
262
+ end
263
+ end
264
+ end
265
+
266
+ assert_raises Chassis::HttpPaymentRequiredError do
267
+ response = faraday.get 'test'
268
+ end
269
+ end
270
+
271
+ def test_raises_a_forbidden_error
272
+ faraday = build do |conn|
273
+ conn.response :server_error_handler
274
+ conn.adapter :test do |stub|
275
+ stub.get 'test' do
276
+ [403, {}, 'dead']
277
+ end
278
+ end
279
+ end
280
+
281
+ assert_raises Chassis::HttpForbiddenError do
282
+ response = faraday.get 'test'
283
+ end
284
+ end
285
+
286
+ def test_raises_a_not_found_error
287
+ faraday = build do |conn|
288
+ conn.response :server_error_handler
289
+ conn.adapter :test do |stub|
290
+ stub.get 'test' do
291
+ [404, {}, 'dead']
292
+ end
293
+ end
294
+ end
295
+
296
+ assert_raises Chassis::HttpNotFoundError do
297
+ response = faraday.get 'test'
298
+ end
299
+ end
300
+
301
+ def test_raises_a_method_not_allowed_error
302
+ faraday = build do |conn|
303
+ conn.response :server_error_handler
304
+ conn.adapter :test do |stub|
305
+ stub.get 'test' do
306
+ [405, {}, 'dead']
307
+ end
308
+ end
309
+ end
310
+
311
+ assert_raises Chassis::HttpMethodNotAllowedError do
312
+ response = faraday.get 'test'
313
+ end
314
+ end
315
+
316
+ def test_raises_an_unacceptable_error
317
+ faraday = build do |conn|
318
+ conn.response :server_error_handler
319
+ conn.adapter :test do |stub|
320
+ stub.get 'test' do
321
+ [406, {}, 'dead']
322
+ end
323
+ end
324
+ end
325
+
326
+ assert_raises Chassis::HttpNotAcceptableError do
327
+ response = faraday.get 'test'
328
+ end
329
+ end
330
+
331
+ def test_raises_a_proxy_auth_error
332
+ faraday = build do |conn|
333
+ conn.response :server_error_handler
334
+ conn.adapter :test do |stub|
335
+ stub.get 'test' do
336
+ [407, {}, 'dead']
337
+ end
338
+ end
339
+ end
340
+
341
+ assert_raises Chassis::HttpProxyAuthenticationRequiredError do
342
+ response = faraday.get 'test'
343
+ end
344
+ end
345
+
346
+ def test_raises_a_timeout_error
347
+ faraday = build do |conn|
348
+ conn.response :server_error_handler
349
+ conn.adapter :test do |stub|
350
+ stub.get 'test' do
351
+ [408, {}, 'dead']
352
+ end
353
+ end
354
+ end
355
+
356
+ assert_raises Chassis::HttpRequestTimeoutError do
357
+ response = faraday.get 'test'
358
+ end
359
+ end
360
+
361
+ def test_raises_a_conflict_error
362
+ faraday = build do |conn|
363
+ conn.response :server_error_handler
364
+ conn.adapter :test do |stub|
365
+ stub.get 'test' do
366
+ [409, {}, 'dead']
367
+ end
368
+ end
369
+ end
370
+
371
+ assert_raises Chassis::HttpConflictError do
372
+ response = faraday.get 'test'
373
+ end
374
+ end
375
+
376
+ def test_raises_a_gone_error
377
+ faraday = build do |conn|
378
+ conn.response :server_error_handler
379
+ conn.adapter :test do |stub|
380
+ stub.get 'test' do
381
+ [410, {}, 'dead']
382
+ end
383
+ end
384
+ end
385
+
386
+ assert_raises Chassis::HttpGoneError do
387
+ response = faraday.get 'test'
388
+ end
389
+ end
390
+
391
+ def test_raises_length_required
392
+ faraday = build do |conn|
393
+ conn.response :server_error_handler
394
+ conn.adapter :test do |stub|
395
+ stub.get 'test' do
396
+ [411, {}, 'dead']
397
+ end
398
+ end
399
+ end
400
+
401
+ assert_raises Chassis::HttpLengthRequiredError do
402
+ response = faraday.get 'test'
403
+ end
404
+ end
405
+
406
+ def test_raises_precondition_failed
407
+ faraday = build do |conn|
408
+ conn.response :server_error_handler
409
+ conn.adapter :test do |stub|
410
+ stub.get 'test' do
411
+ [412, {}, 'dead']
412
+ end
413
+ end
414
+ end
415
+
416
+ assert_raises Chassis::HttpPreconditionFailedError do
417
+ response = faraday.get 'test'
418
+ end
419
+ end
420
+
421
+ def test_raises_request_entity_too_large
422
+ faraday = build do |conn|
423
+ conn.response :server_error_handler
424
+ conn.adapter :test do |stub|
425
+ stub.get 'test' do
426
+ [413, {}, 'dead']
427
+ end
428
+ end
429
+ end
430
+
431
+ assert_raises Chassis::HttpRequestEntityTooLargeError do
432
+ response = faraday.get 'test'
433
+ end
434
+ end
435
+
436
+ def test_raises_request_uri_too_long
437
+ faraday = build do |conn|
438
+ conn.response :server_error_handler
439
+ conn.adapter :test do |stub|
440
+ stub.get 'test' do
441
+ [414, {}, 'dead']
442
+ end
443
+ end
444
+ end
445
+
446
+ assert_raises Chassis::HttpRequestUriTooLongError do
447
+ response = faraday.get 'test'
448
+ end
449
+ end
450
+
451
+ def test_raises_unsupported_media_type
452
+ faraday = build do |conn|
453
+ conn.response :server_error_handler
454
+ conn.adapter :test do |stub|
455
+ stub.get 'test' do
456
+ [415, {}, 'dead']
457
+ end
458
+ end
459
+ end
460
+
461
+ assert_raises Chassis::HttpUnsupportedMediaTypeError do
462
+ response = faraday.get 'test'
463
+ end
464
+ end
465
+
466
+ def test_raises_range_not_satisfiable
467
+ faraday = build do |conn|
468
+ conn.response :server_error_handler
469
+ conn.adapter :test do |stub|
470
+ stub.get 'test' do
471
+ [416, {}, 'dead']
472
+ end
473
+ end
474
+ end
475
+
476
+ assert_raises Chassis::HttpRequestRangeNotSatisfiableError do
477
+ response = faraday.get 'test'
478
+ end
479
+ end
480
+
481
+ def test_raises_expectation_failed
482
+ faraday = build do |conn|
483
+ conn.response :server_error_handler
484
+ conn.adapter :test do |stub|
485
+ stub.get 'test' do
486
+ [417, {}, 'dead']
487
+ end
488
+ end
489
+ end
490
+
491
+ assert_raises Chassis::HttpExpectationFailedError do
492
+ response = faraday.get 'test'
493
+ end
494
+ end
495
+
496
+ def test_raises_unprocessable_entity
497
+ faraday = build do |conn|
498
+ conn.response :server_error_handler
499
+ conn.adapter :test do |stub|
500
+ stub.get 'test' do
501
+ [422, {}, 'dead']
502
+ end
503
+ end
504
+ end
505
+
506
+ assert_raises Chassis::HttpUnprocessableEntityError do
507
+ response = faraday.get 'test'
508
+ end
509
+ end
510
+
511
+ def test_raises_locked_error
512
+ faraday = build do |conn|
513
+ conn.response :server_error_handler
514
+ conn.adapter :test do |stub|
515
+ stub.get 'test' do
516
+ [423, {}, 'dead']
517
+ end
518
+ end
519
+ end
520
+
521
+ assert_raises Chassis::HttpLockedError do
522
+ response = faraday.get 'test'
523
+ end
524
+ end
525
+
526
+ def test_raises_failed_dependency_error
527
+ faraday = build do |conn|
528
+ conn.response :server_error_handler
529
+ conn.adapter :test do |stub|
530
+ stub.get 'test' do
531
+ [424, {}, 'dead']
532
+ end
533
+ end
534
+ end
535
+
536
+ assert_raises Chassis::HttpFailedDependencyError do
537
+ response = faraday.get 'test'
538
+ end
539
+ end
540
+
541
+ def test_raises_upgrade_require_error
542
+ faraday = build do |conn|
543
+ conn.response :server_error_handler
544
+ conn.adapter :test do |stub|
545
+ stub.get 'test' do
546
+ [426, {}, 'dead']
547
+ end
548
+ end
549
+ end
550
+
551
+ assert_raises Chassis::HttpUpgradeRequiredError do
552
+ response = faraday.get 'test'
553
+ end
554
+ end
555
+
556
+ def test_raises_internal_server_error
557
+ faraday = build do |conn|
558
+ conn.response :server_error_handler
559
+ conn.adapter :test do |stub|
560
+ stub.get 'test' do
561
+ [500, {}, 'dead']
562
+ end
563
+ end
564
+ end
565
+
566
+ assert_raises Chassis::HttpInternalServerError do
567
+ response = faraday.get 'test'
568
+ end
569
+ end
570
+
571
+ def test_raises_not_implemented_error
572
+ faraday = build do |conn|
573
+ conn.response :server_error_handler
574
+ conn.adapter :test do |stub|
575
+ stub.get 'test' do
576
+ [501, {}, 'dead']
577
+ end
578
+ end
579
+ end
580
+
581
+ assert_raises Chassis::HttpNotImplementedError do
582
+ response = faraday.get 'test'
583
+ end
584
+ end
585
+
586
+ def test_raises_bad_gateway_error
587
+ faraday = build do |conn|
588
+ conn.response :server_error_handler
589
+ conn.adapter :test do |stub|
590
+ stub.get 'test' do
591
+ [502, {}, 'dead']
592
+ end
593
+ end
594
+ end
595
+
596
+ assert_raises Chassis::HttpBadGatewayError do
597
+ response = faraday.get 'test'
598
+ end
599
+ end
600
+
601
+ def test_raises_service_unavailable
602
+ faraday = build do |conn|
603
+ conn.response :server_error_handler
604
+ conn.adapter :test do |stub|
605
+ stub.get 'test' do
606
+ [503, {}, 'dead']
607
+ end
608
+ end
609
+ end
610
+
611
+ assert_raises Chassis::HttpServiceUnavailableError do
612
+ response = faraday.get 'test'
613
+ end
614
+ end
615
+
616
+ def test_raises_gateway_timeout
617
+ faraday = build do |conn|
618
+ conn.response :server_error_handler
619
+ conn.adapter :test do |stub|
620
+ stub.get 'test' do
621
+ [504, {}, 'dead']
622
+ end
623
+ end
624
+ end
625
+
626
+ assert_raises Chassis::HttpGatewayTimeoutError do
627
+ response = faraday.get 'test'
628
+ end
629
+ end
630
+
631
+ def test_raises_http_version_not_supported_error
632
+ faraday = build do |conn|
633
+ conn.response :server_error_handler
634
+ conn.adapter :test do |stub|
635
+ stub.get 'test' do
636
+ [505, {}, 'dead']
637
+ end
638
+ end
639
+ end
640
+
641
+ assert_raises Chassis::HttpVersionNotSupportedError do
642
+ response = faraday.get 'test'
643
+ end
644
+ end
645
+
646
+ def test_raises_insuffcient_storage
647
+ faraday = build do |conn|
648
+ conn.response :server_error_handler
649
+ conn.adapter :test do |stub|
650
+ stub.get 'test' do
651
+ [507, {}, 'dead']
652
+ end
653
+ end
654
+ end
655
+
656
+ assert_raises Chassis::HttpInsufficientStorageError do
657
+ response = faraday.get 'test'
658
+ end
659
+ end
660
+
661
+ def test_raises_not_extended_error
662
+ faraday = build do |conn|
663
+ conn.response :server_error_handler
664
+ conn.adapter :test do |stub|
665
+ stub.get 'test' do
666
+ [510, {}, 'dead']
667
+ end
668
+ end
669
+ end
670
+
671
+ assert_raises Chassis::HttpNotExtendedError do
672
+ response = faraday.get 'test'
673
+ end
674
+ end
675
+
676
+ def test_server_errors_contain_useful_information
677
+ faraday = build 'http://example.com' do |conn|
678
+ conn.response :server_error_handler
679
+ conn.adapter :test do |stub|
680
+ stub.get 'test.error' do
681
+ [500, {}, 'dead']
682
+ end
683
+ end
684
+ end
685
+
686
+ begin
687
+ faraday.get 'test.error'
688
+ rescue => ex
689
+ exception = ex
690
+ end
691
+
692
+ assert exception
693
+ msg = exception.to_s
694
+ assert_includes msg, "http://example.com/test.error"
695
+ end
696
+
697
+ def test_has_factory_for_faraday_connections
698
+ faraday = Chassis.faraday 'http://example.com'
699
+
700
+ stack = faraday.builder.handlers
701
+
702
+ assert_includes stack, Chassis::Instrumentation
703
+ assert_includes stack, Chassis::EncodeJson
704
+ assert_includes stack, Chassis::ParseJson
705
+ assert_includes stack, Chassis::ServerErrorHandler
706
+ assert_includes stack, Chassis::Logging
707
+ end
708
+
709
+ def test_factory_can_change_the_namespace
710
+ faraday = Chassis.faraday 'http://example.com', namespace: 'test' do |conn|
711
+ conn.adapter :test do |stub|
712
+ stub.get 'test' do
713
+ [200, {'Content-Type' => 'application/json'}, JSON.dump(foo: 'bar')]
714
+ end
715
+ end
716
+ end
717
+
718
+ faraday.get 'test'
719
+
720
+ refute_empty stats.timers
721
+ timer = stats.timers.first
722
+
723
+ assert_equal 'test.get', timer.name
724
+ end
725
+
726
+ def test_factory_can_change_the_logger
727
+ stream = StringIO.new
728
+ logger = Logger.new stream
729
+ logger.level = :debug
730
+
731
+ faraday = Chassis.faraday 'http://example.com', logger: logger do |conn|
732
+ conn.adapter :test do |stub|
733
+ stub.get 'test' do
734
+ [200, {}, 'dead']
735
+ end
736
+ end
737
+ end
738
+
739
+ faraday.get 'test', { foo: 'bar' }, { 'This-Header' => 'has_a_value' }
740
+
741
+ stream.rewind ; content = stream.read
742
+
743
+ assert_includes content, 'http://example.com/test'
744
+ assert_includes content, 'This-Header'
745
+ assert_includes content, 'has_a_value'
746
+ assert_includes content, 'foo'
747
+ assert_includes content, 'bar'
748
+ end
749
+ end