telnyx 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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +4 -0
  3. data/.github/ISSUE_TEMPLATE.md +5 -0
  4. data/.gitignore +9 -0
  5. data/.rubocop.yml +32 -0
  6. data/.rubocop_todo.yml +50 -0
  7. data/.travis.yml +42 -0
  8. data/CHANGELOG.md +2 -0
  9. data/CONTRIBUTORS +0 -0
  10. data/Gemfile +40 -0
  11. data/Guardfile +8 -0
  12. data/LICENSE +22 -0
  13. data/README.md +173 -0
  14. data/Rakefile +28 -0
  15. data/VERSION +1 -0
  16. data/bin/telnyx-console +16 -0
  17. data/lib/telnyx.rb +151 -0
  18. data/lib/telnyx/api_operations/create.rb +12 -0
  19. data/lib/telnyx/api_operations/delete.rb +13 -0
  20. data/lib/telnyx/api_operations/list.rb +29 -0
  21. data/lib/telnyx/api_operations/nested_resource.rb +63 -0
  22. data/lib/telnyx/api_operations/request.rb +57 -0
  23. data/lib/telnyx/api_operations/save.rb +103 -0
  24. data/lib/telnyx/api_resource.rb +69 -0
  25. data/lib/telnyx/available_phone_number.rb +9 -0
  26. data/lib/telnyx/errors.rb +166 -0
  27. data/lib/telnyx/event.rb +9 -0
  28. data/lib/telnyx/list_object.rb +155 -0
  29. data/lib/telnyx/message.rb +9 -0
  30. data/lib/telnyx/messaging_phone_number.rb +10 -0
  31. data/lib/telnyx/messaging_profile.rb +32 -0
  32. data/lib/telnyx/messaging_sender_id.rb +12 -0
  33. data/lib/telnyx/messaging_short_code.rb +10 -0
  34. data/lib/telnyx/number_order.rb +11 -0
  35. data/lib/telnyx/number_reservation.rb +11 -0
  36. data/lib/telnyx/public_key.rb +7 -0
  37. data/lib/telnyx/singleton_api_resource.rb +24 -0
  38. data/lib/telnyx/telnyx_client.rb +545 -0
  39. data/lib/telnyx/telnyx_object.rb +521 -0
  40. data/lib/telnyx/telnyx_response.rb +50 -0
  41. data/lib/telnyx/util.rb +328 -0
  42. data/lib/telnyx/version.rb +5 -0
  43. data/lib/telnyx/webhook.rb +66 -0
  44. data/telnyx.gemspec +25 -0
  45. data/test/api_stub_helpers.rb +1 -0
  46. data/test/openapi/README.md +9 -0
  47. data/test/telnyx/api_operations_test.rb +85 -0
  48. data/test/telnyx/api_resource_test.rb +293 -0
  49. data/test/telnyx/available_phone_number_test.rb +14 -0
  50. data/test/telnyx/errors_test.rb +23 -0
  51. data/test/telnyx/list_object_test.rb +244 -0
  52. data/test/telnyx/message_test.rb +19 -0
  53. data/test/telnyx/messaging_phone_number_test.rb +33 -0
  54. data/test/telnyx/messaging_profile_test.rb +70 -0
  55. data/test/telnyx/messaging_sender_id_test.rb +46 -0
  56. data/test/telnyx/messaging_short_code_test.rb +33 -0
  57. data/test/telnyx/number_order_test.rb +39 -0
  58. data/test/telnyx/number_reservation_test.rb +12 -0
  59. data/test/telnyx/public_key_test.rb +13 -0
  60. data/test/telnyx/telnyx_client_test.rb +631 -0
  61. data/test/telnyx/telnyx_object_test.rb +497 -0
  62. data/test/telnyx/telnyx_response_test.rb +49 -0
  63. data/test/telnyx/util_test.rb +380 -0
  64. data/test/telnyx/webhook_test.rb +108 -0
  65. data/test/telnyx_mock.rb +78 -0
  66. data/test/telnyx_test.rb +40 -0
  67. data/test/test_data.rb +149 -0
  68. data/test/test_helper.rb +73 -0
  69. metadata +162 -0
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../test_helper"
4
+
5
+ module Telnyx
6
+ class TelnyxNumberOrderTest < Test::Unit::TestCase
7
+ should "be listable" do
8
+ number_orders = Telnyx::NumberOrder.list
9
+ assert_requested :get, "#{Telnyx.api_base}/v2/number_orders"
10
+ assert_kind_of Telnyx::ListObject, number_orders
11
+ assert_kind_of Telnyx::NumberOrder, number_orders.first
12
+ end
13
+
14
+ should "be creatable" do
15
+ Telnyx::NumberOrder.create(
16
+ phone_numbers: [
17
+ { "phone_number" => "+12223334444", "regulatory_requirements" => [] },
18
+ ],
19
+ customer_reference: "MY REF 001",
20
+ connection_id: "442191469269222625"
21
+ )
22
+ assert_requested :post, "#{Telnyx.api_base}/v2/number_orders"
23
+ end
24
+
25
+ should "be retrievable" do
26
+ number_order = Telnyx::NumberOrder.retrieve "123"
27
+ assert_requested :get, "#{Telnyx.api_base}/v2/number_orders/123"
28
+ assert_kind_of Telnyx::NumberOrder, number_order
29
+ end
30
+
31
+ should "be savable" do
32
+ number_order = Telnyx::NumberOrder.retrieve "123"
33
+ number_order.customer_reference = "foobar"
34
+ number_order.save
35
+ assert_requested :patch, "#{Telnyx.api_base}/v2/number_orders/123"
36
+ assert_kind_of Telnyx::NumberOrder, number_order
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telnyx
4
+ class NumberReservationTest < Test::Unit::TestCase
5
+ should "be listable" do
6
+ number_reservations = Telnyx::NumberReservation.list
7
+ assert_requested :get, "#{Telnyx.api_base}/v2/number_reservations"
8
+ assert_kind_of Telnyx::ListObject, number_reservations
9
+ assert_kind_of Telnyx::NumberReservation, number_reservations.first
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require ::File.expand_path("../../test_helper", __FILE__)
4
+
5
+ module Telnyx
6
+ class PublicKeyTest < Test::Unit::TestCase
7
+ should "be retrievable" do
8
+ public_key = Telnyx::PublicKey.retrieve
9
+ assert_requested :get, "#{Telnyx.api_base}/v2/public_key"
10
+ assert public_key.is_a?(Telnyx::PublicKey)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,631 @@
1
+ # frozen_string_literal: true
2
+
3
+ require ::File.expand_path("../../test_helper", __FILE__)
4
+
5
+ module Telnyx
6
+ class TelnyxClientTest < Test::Unit::TestCase
7
+ context ".active_client" do
8
+ should "be .default_client outside of #request" do
9
+ assert_equal TelnyxClient.default_client, TelnyxClient.active_client
10
+ end
11
+
12
+ should "be active client inside of #request" do
13
+ client = TelnyxClient.new
14
+ client.request do
15
+ assert_equal client, TelnyxClient.active_client
16
+ end
17
+ end
18
+ end
19
+
20
+ context ".default_client" do
21
+ should "be a TelnyxClient" do
22
+ assert_kind_of TelnyxClient, TelnyxClient.default_client
23
+ end
24
+
25
+ should "be a different client on each thread" do
26
+ other_thread_client = nil
27
+ thread = Thread.new do
28
+ other_thread_client = TelnyxClient.default_client
29
+ end
30
+ thread.join
31
+ refute_equal TelnyxClient.default_client, other_thread_client
32
+ end
33
+ end
34
+
35
+ context ".default_conn" do
36
+ should "be a Faraday::Connection" do
37
+ assert_kind_of Faraday::Connection, TelnyxClient.default_conn
38
+ end
39
+
40
+ should "be a different connection on each thread" do
41
+ other_thread_conn = nil
42
+ thread = Thread.new do
43
+ other_thread_conn = TelnyxClient.default_conn
44
+ end
45
+ thread.join
46
+ refute_equal TelnyxClient.default_conn, other_thread_conn
47
+ end
48
+ end
49
+
50
+ context ".should_retry?" do
51
+ setup do
52
+ Telnyx.stubs(:max_network_retries).returns(2)
53
+ end
54
+
55
+ should "retry on timeout" do
56
+ assert TelnyxClient.should_retry?(Faraday::TimeoutError.new(""), 0)
57
+ end
58
+
59
+ should "retry on a failed connection" do
60
+ assert TelnyxClient.should_retry?(Faraday::ConnectionFailed.new(""), 0)
61
+ end
62
+
63
+ should "not retry at maximum count" do
64
+ refute TelnyxClient.should_retry?(RuntimeError.new, Telnyx.max_network_retries)
65
+ end
66
+
67
+ should "not retry on a certificate validation error" do
68
+ refute TelnyxClient.should_retry?(Faraday::SSLError.new(""), 0)
69
+ end
70
+ end
71
+
72
+ context ".sleep_time" do
73
+ should "should grow exponentially" do
74
+ TelnyxClient.stubs(:rand).returns(1)
75
+ Telnyx.stubs(:max_network_retry_delay).returns(999)
76
+ assert_equal(Telnyx.initial_network_retry_delay, TelnyxClient.sleep_time(1))
77
+ assert_equal(Telnyx.initial_network_retry_delay * 2, TelnyxClient.sleep_time(2))
78
+ assert_equal(Telnyx.initial_network_retry_delay * 4, TelnyxClient.sleep_time(3))
79
+ assert_equal(Telnyx.initial_network_retry_delay * 8, TelnyxClient.sleep_time(4))
80
+ end
81
+
82
+ should "enforce the max_network_retry_delay" do
83
+ TelnyxClient.stubs(:rand).returns(1)
84
+ Telnyx.stubs(:initial_network_retry_delay).returns(1)
85
+ Telnyx.stubs(:max_network_retry_delay).returns(2)
86
+ assert_equal(1, TelnyxClient.sleep_time(1))
87
+ assert_equal(2, TelnyxClient.sleep_time(2))
88
+ assert_equal(2, TelnyxClient.sleep_time(3))
89
+ assert_equal(2, TelnyxClient.sleep_time(4))
90
+ end
91
+
92
+ should "add some randomness" do
93
+ random_value = 0.8
94
+ TelnyxClient.stubs(:rand).returns(random_value)
95
+ Telnyx.stubs(:initial_network_retry_delay).returns(1)
96
+ Telnyx.stubs(:max_network_retry_delay).returns(8)
97
+
98
+ base_value = Telnyx.initial_network_retry_delay * (0.5 * (1 + random_value))
99
+
100
+ # the initial value cannot be smaller than the base,
101
+ # so the randomness is ignored
102
+ assert_equal(Telnyx.initial_network_retry_delay, TelnyxClient.sleep_time(1))
103
+
104
+ # after the first one, the randomness is applied
105
+ assert_equal(base_value * 2, TelnyxClient.sleep_time(2))
106
+ assert_equal(base_value * 4, TelnyxClient.sleep_time(3))
107
+ assert_equal(base_value * 8, TelnyxClient.sleep_time(4))
108
+ end
109
+ end
110
+
111
+ context "#initialize" do
112
+ should "set Telnyx.default_conn" do
113
+ client = TelnyxClient.new
114
+ assert_equal TelnyxClient.default_conn, client.conn
115
+ end
116
+
117
+ should "set a different connection if one was specified" do
118
+ conn = Faraday.new
119
+ client = TelnyxClient.new(conn)
120
+ assert_equal conn, client.conn
121
+ end
122
+ end
123
+
124
+ context "#execute_request" do
125
+ context "headers" do
126
+ should "support literal headers" do
127
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
128
+ .with(headers: { "Authorization" => "Bearer foobar" })
129
+ .to_return(body: JSON.generate(record_type: "messaging_profile"))
130
+
131
+ client = TelnyxClient.new
132
+ client.execute_request(:post, "/v2/messaging_profiles",
133
+ headers: { "Authorization" => "Bearer foobar" })
134
+ end
135
+
136
+ should "support RestClient-style header keys" do
137
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
138
+ .with(headers: { "Telnyx-Account" => "bar" })
139
+ .to_return(body: JSON.generate(record_type: "messaging_profile"))
140
+
141
+ client = TelnyxClient.new
142
+ client.execute_request(:post, "/v2/messaging_profiles",
143
+ headers: { telnyx_account: "bar" })
144
+ end
145
+ end
146
+
147
+ context "logging" do
148
+ setup do
149
+ # Freeze time for the purposes of the `elapsed` parameter that we
150
+ # emit for responses. I didn't want to bring in a new dependency for
151
+ # this, but Mocha's `anything` parameter can't match inside of a hash
152
+ # and is therefore not useful for this purpose. If we switch over to
153
+ # rspec-mocks at some point, we can probably remove Timecop from the
154
+ # project.
155
+ Timecop.freeze(Time.local(1990))
156
+ end
157
+
158
+ teardown do
159
+ Timecop.return
160
+ end
161
+
162
+ should "produce appropriate logging" do
163
+ body = JSON.generate(object: "account")
164
+
165
+ Util.expects(:log_info).with("Request to Telnyx API",
166
+ method: :post,
167
+ num_retries: 0,
168
+ path: "/v2/messaging_profiles")
169
+ Util.expects(:log_debug).with("Request details",
170
+ body: "{}",
171
+ query_params: nil)
172
+
173
+ Util.expects(:log_info).with("Response from Telnyx API",
174
+ elapsed: 0.0,
175
+ method: :post,
176
+ path: "/v2/messaging_profiles",
177
+ request_id: "req_123",
178
+ status: 200)
179
+ Util.expects(:log_debug).with("Response details",
180
+ body: body,
181
+ # idempotency_key: "abc",
182
+ request_id: "req_123")
183
+
184
+ stub_post = stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
185
+ .to_return(
186
+ body: body,
187
+ headers: {
188
+ "X-Request-Id" => "req_123",
189
+ }
190
+ )
191
+
192
+ client = TelnyxClient.new
193
+ client.execute_request(:post, "/v2/messaging_profiles")
194
+ assert_requested(stub_post)
195
+ end
196
+
197
+ should "produce logging on API error" do
198
+ Util.expects(:log_info).with("Request to Telnyx API",
199
+ method: :post,
200
+ num_retries: 0,
201
+ path: "/v2/messaging_profiles")
202
+ Util.expects(:log_info).with("Response from Telnyx API",
203
+ elapsed: 0.0,
204
+ method: :post,
205
+ path: "/v2/messaging_profiles",
206
+ request_id: nil,
207
+ status: 500)
208
+
209
+ error = {
210
+ code: "code",
211
+ detail: "detail",
212
+ source: "source",
213
+ title: "title",
214
+ }
215
+ Util.expects(:log_error).with("Telnyx API error",
216
+ status: 500,
217
+ error_code: error[:code],
218
+ error_detail: error[:detail],
219
+ error_source: error[:source],
220
+ error_title: error[:title],
221
+ request_id: nil)
222
+
223
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
224
+ .to_return(
225
+ body: JSON.generate(errors: [error]),
226
+ status: 500
227
+ )
228
+
229
+ client = TelnyxClient.new
230
+ assert_raises Telnyx::APIError do
231
+ client.execute_request(:post, "/v2/messaging_profiles")
232
+ end
233
+ end
234
+ end
235
+
236
+ context "Telnyx-Account header" do
237
+ should "use a globally set header" do
238
+ begin
239
+ old = Telnyx.telnyx_account
240
+ Telnyx.telnyx_account = "acct_1234"
241
+
242
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
243
+ .with(headers: { "Telnyx-Account" => Telnyx.telnyx_account })
244
+ .to_return(body: JSON.generate(object: "account"))
245
+
246
+ client = TelnyxClient.new
247
+ client.execute_request(:post, "/v2/messaging_profiles")
248
+ ensure
249
+ Telnyx.telnyx_account = old
250
+ end
251
+ end
252
+
253
+ should "use a locally set header" do
254
+ telnyx_account = "acct_0000"
255
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
256
+ .with(headers: { "Telnyx-Account" => telnyx_account })
257
+ .to_return(body: JSON.generate(object: "account"))
258
+
259
+ client = TelnyxClient.new
260
+ client.execute_request(:post, "/v2/messaging_profiles",
261
+ headers: { telnyx_account: telnyx_account })
262
+ end
263
+
264
+ should "not send it otherwise" do
265
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
266
+ .with do |req|
267
+ req.headers["Telnyx-Account"].nil?
268
+ end.to_return(body: JSON.generate(object: "account"))
269
+
270
+ client = TelnyxClient.new
271
+ client.execute_request(:post, "/v2/messaging_profiles")
272
+ end
273
+ end
274
+
275
+ context "app_info" do
276
+ should "send app_info if set" do
277
+ begin
278
+ old = Telnyx.app_info
279
+ Telnyx.set_app_info(
280
+ "MyAwesomePlugin",
281
+ partner_id: "partner_1234",
282
+ url: "https://myawesomeplugin.info",
283
+ version: "1.2.34"
284
+ )
285
+
286
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
287
+ .with do |req|
288
+ assert_equal \
289
+ "Telnyx/v2 RubyBindings/#{Telnyx::VERSION} " \
290
+ "MyAwesomePlugin/1.2.34 (https://myawesomeplugin.info)",
291
+ req.headers["User-Agent"]
292
+
293
+ data = JSON.parse(req.headers["X-Telnyx-Client-User-Agent"],
294
+ symbolize_names: true)
295
+
296
+ assert_equal({
297
+ name: "MyAwesomePlugin",
298
+ partner_id: "partner_1234",
299
+ url: "https://myawesomeplugin.info",
300
+ version: "1.2.34",
301
+ }, data[:application])
302
+
303
+ true
304
+ end.to_return(body: JSON.generate(record_type: "messaging_profile"))
305
+
306
+ client = TelnyxClient.new
307
+ client.execute_request(:post, "/v2/messaging_profiles")
308
+ ensure
309
+ Telnyx.app_info = old
310
+ end
311
+ end
312
+ end
313
+
314
+ context "error handling" do
315
+ should "handle error response with empty body" do
316
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
317
+ .to_return(body: "", status: 500)
318
+
319
+ client = TelnyxClient.new
320
+ e = assert_raises Telnyx::APIError do
321
+ client.execute_request(:post, "/v2/messaging_profiles")
322
+ end
323
+
324
+ assert_equal 'Invalid response object from API: "" (HTTP response code was 500)', e.message
325
+ end
326
+
327
+ should "handle success response with empty body" do
328
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
329
+ .to_return(body: "", status: 200)
330
+
331
+ client = TelnyxClient.new
332
+ e = assert_raises Telnyx::APIError do
333
+ client.execute_request(:post, "/v2/messaging_profiles")
334
+ end
335
+
336
+ assert_equal 'Invalid response object from API: "" (HTTP response code was 200)', e.message
337
+ end
338
+
339
+ should "handle error response with unknown value" do
340
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
341
+ .to_return(body: JSON.generate(bar: "foo"), status: 500)
342
+
343
+ client = TelnyxClient.new
344
+ e = assert_raises Telnyx::APIError do
345
+ client.execute_request(:post, "/v2/messaging_profiles")
346
+ end
347
+
348
+ assert_equal 'Invalid response object from API: "{\"bar\":\"foo\"}" (HTTP response code was 500)', e.message
349
+ end
350
+
351
+ should "raise InvalidRequestError on other 400" do
352
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
353
+ .to_return(body: JSON.generate(make_invalid_id_error), status: 400)
354
+ client = TelnyxClient.new
355
+ begin
356
+ client.execute_request(:post, "/v2/messaging_profiles")
357
+ rescue Telnyx::InvalidRequestError => e
358
+ assert_equal(400, e.http_status)
359
+ assert_equal(true, e.json_body.is_a?(Hash))
360
+ end
361
+ end
362
+
363
+ should "raise AuthenticationError on 401" do
364
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
365
+ .to_return(body: JSON.generate(make_authentication_failed_error), status: 401)
366
+ client = TelnyxClient.new
367
+ begin
368
+ client.execute_request(:post, "/v2/messaging_profiles")
369
+ rescue Telnyx::AuthenticationError => e
370
+ assert_equal(401, e.http_status)
371
+ assert_equal(true, e.json_body.is_a?(Hash))
372
+ end
373
+ end
374
+
375
+ should "raise PermissionError on 403" do
376
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
377
+ .to_return(body: JSON.generate(make_authorization_failed_error), status: 403)
378
+ client = TelnyxClient.new
379
+ begin
380
+ client.execute_request(:post, "/v2/messaging_profiles")
381
+ rescue Telnyx::PermissionError => e
382
+ assert_equal(403, e.http_status)
383
+ assert_equal(true, e.json_body.is_a?(Hash))
384
+ end
385
+ end
386
+
387
+ should "raise ResourceNotFoundError on 404" do
388
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
389
+ .to_return(body: JSON.generate(make_resource_not_found_error), status: 404)
390
+ client = TelnyxClient.new
391
+ begin
392
+ client.execute_request(:post, "/v2/messaging_profiles")
393
+ rescue Telnyx::ResourceNotFoundError => e
394
+ assert_equal(404, e.http_status)
395
+ assert_equal(true, e.json_body.is_a?(Hash))
396
+ end
397
+ end
398
+
399
+ should "raise MethodNotSupportedError on 405" do
400
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
401
+ .to_return(body: JSON.generate(make_method_not_supported_error), status: 405)
402
+ client = TelnyxClient.new
403
+ begin
404
+ client.execute_request(:post, "/v2/messaging_profiles")
405
+ rescue Telnyx::MethodNotSupportedError => e
406
+ assert_equal(405, e.http_status)
407
+ assert_equal(true, e.json_body.is_a?(Hash))
408
+ end
409
+ end
410
+
411
+ should "raise TimeoutError on 408" do
412
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
413
+ .to_return(body: JSON.generate(make_timeout_error), status: 408)
414
+ client = TelnyxClient.new
415
+ begin
416
+ client.execute_request(:post, "/v2/messaging_profiles")
417
+ rescue Telnyx::TimeoutError => e
418
+ assert_equal(408, e.http_status)
419
+ assert_equal(true, e.json_body.is_a?(Hash))
420
+ end
421
+ end
422
+
423
+ should "raise InvalidParametersError on 422" do
424
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
425
+ .to_return(body: JSON.generate(make_parameters_error), status: 422)
426
+ client = TelnyxClient.new
427
+ begin
428
+ client.execute_request(:post, "/v2/messaging_profiles")
429
+ rescue Telnyx::InvalidParametersError => e
430
+ assert_equal(422, e.http_status)
431
+ assert_equal(true, e.json_body.is_a?(Hash))
432
+ end
433
+ end
434
+
435
+ should "raise RateLimitError on 429" do
436
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
437
+ .to_return(body: JSON.generate(make_rate_limit_error), status: 429)
438
+ client = TelnyxClient.new
439
+ begin
440
+ client.execute_request(:post, "/v2/messaging_profiles")
441
+ rescue Telnyx::RateLimitError => e
442
+ assert_equal(429, e.http_status)
443
+ assert_equal(true, e.json_body.is_a?(Hash))
444
+ end
445
+ end
446
+
447
+ should "raise APIError on 500" do
448
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
449
+ .to_return(body: JSON.generate(make_api_error), status: 500)
450
+ client = TelnyxClient.new
451
+ begin
452
+ client.execute_request(:post, "/v2/messaging_profiles")
453
+ rescue Telnyx::APIError => e
454
+ assert_equal(500, e.http_status)
455
+ assert_equal(true, e.json_body.is_a?(Hash))
456
+ end
457
+ end
458
+
459
+ should "raise ServiceUnavailableError on 503" do
460
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
461
+ .to_return(body: JSON.generate(make_service_unavailable_error), status: 503)
462
+ client = TelnyxClient.new
463
+ begin
464
+ client.execute_request(:post, "/v2/messaging_profiles")
465
+ rescue Telnyx::ServiceUnavailableError => e
466
+ assert_equal(503, e.http_status)
467
+ assert_equal(true, e.json_body.is_a?(Hash))
468
+ end
469
+ end
470
+ end
471
+
472
+ context "retry logic" do
473
+ setup do
474
+ Telnyx.stubs(:max_network_retries).returns(2)
475
+ end
476
+
477
+ should "retry failed requests and raise if error persists" do
478
+ TelnyxClient.expects(:sleep_time).at_least_once.returns(0)
479
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
480
+ .to_raise(Errno::ECONNREFUSED.new)
481
+
482
+ client = TelnyxClient.new
483
+ err = assert_raises Telnyx::APIConnectionError do
484
+ client.execute_request(:post, "/v2/messaging_profiles")
485
+ end
486
+ assert_match(/Request was retried 2 times/, err.message)
487
+ end
488
+
489
+ should "retry failed requests and return successful response" do
490
+ TelnyxClient.expects(:sleep_time).at_least_once.returns(0)
491
+
492
+ i = 0
493
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
494
+ .to_return do |_|
495
+ if i < 2
496
+ i += 1
497
+ raise Errno::ECONNREFUSED
498
+ else
499
+ { body: JSON.generate("id" => "myid") }
500
+ end
501
+ end
502
+
503
+ client = TelnyxClient.new
504
+ client.execute_request(:post, "/v2/messaging_profiles")
505
+ end
506
+ end
507
+
508
+ context "params serialization" do
509
+ should "allows empty strings in params" do
510
+ client = TelnyxClient.new
511
+ stub_get = stub_request(
512
+ :get,
513
+ "#{Telnyx.api_base}/v2/messaging_profiles/123?"
514
+ )
515
+ .with(query: {
516
+ "page[token]" => " ",
517
+ })
518
+ .to_return(body: JSON.generate(data: { record_type: "messaging_profile", id: "foo" }))
519
+ client.execute_request(:get, "/v2/messaging_profiles/123", params: {
520
+ "page[token]" => " ",
521
+ })
522
+ assert_requested(stub_get)
523
+ end
524
+
525
+ should "filter nils in params" do
526
+ client = TelnyxClient.new
527
+ client.execute_request(:get, "/v2/messaging_profiles", params: {
528
+ "page[token]" => nil,
529
+ })
530
+ assert_requested(
531
+ :get,
532
+ "#{Telnyx.api_base}/v2/messaging_profiles?",
533
+ query: {}
534
+ )
535
+ end
536
+
537
+ should "merge query parameters in URL and params" do
538
+ client = TelnyxClient.new
539
+ stub_get = stub_request(
540
+ :get,
541
+ "#{Telnyx.api_base}/v2/messaging_profiles?"
542
+ )
543
+ .with(query: {
544
+ page: { number: 10, token: "foo" },
545
+ })
546
+ .to_return(body: JSON.generate(data: { record_type: "messaging_profile", id: "foo" }))
547
+
548
+ client.execute_request(:get, "/v2/messaging_profiles?page[token]=foo", params: {
549
+ page: { number: 10 },
550
+ })
551
+
552
+ assert_requested(stub_get)
553
+ end
554
+
555
+ should "prefer query parameters in params when specified in URL as well" do
556
+ client = TelnyxClient.new
557
+ stub_get = stub_request(
558
+ :get,
559
+ "#{Telnyx.api_base}/v2/messaging_profiles?"
560
+ )
561
+ .with(query: {
562
+ format: "xml",
563
+ })
564
+ .to_return(body: JSON.generate(data: { record_type: "messaging_profile", id: "foo" }))
565
+ client.execute_request(:get, "/v2/messaging_profiles?format=json", params: {
566
+ format: "xml",
567
+ })
568
+ assert_requested(stub_get)
569
+ end
570
+ end
571
+ end
572
+
573
+ context "#request" do
574
+ should "return a result and response object" do
575
+ stub_request(:post, "#{Telnyx.api_base}/v2/messaging_profiles")
576
+ .to_return(body: JSON.generate(record_type: "messaging_profile"))
577
+
578
+ client = TelnyxClient.new
579
+ messaging_profile, resp = client.request { MessagingProfile.create }
580
+
581
+ assert messaging_profile.is_a?(MessagingProfile)
582
+ assert resp.is_a?(TelnyxResponse)
583
+ assert_equal 200, resp.http_status
584
+ end
585
+
586
+ should "return the value of given block" do
587
+ client = TelnyxClient.new
588
+ ret, = client.request { 7 }
589
+ assert_equal 7, ret
590
+ end
591
+
592
+ should "reset local thread state after a call" do
593
+ begin
594
+ Thread.current[:telnyx_client] = :telnyx_client
595
+
596
+ client = TelnyxClient.new
597
+ client.request {}
598
+
599
+ assert_equal :telnyx_client, Thread.current[:telnyx_client]
600
+ ensure
601
+ Thread.current[:telnyx_client] = nil
602
+ end
603
+ end
604
+ end
605
+ end
606
+
607
+ class SystemProfilerTest < Test::Unit::TestCase
608
+ context "#uname" do
609
+ should "run without failure" do
610
+ # Don't actually check the result because we try a variety of different
611
+ # strategies that will have different results depending on where this
612
+ # test and running. We're mostly making sure that no exception is thrown.
613
+ _ = TelnyxClient::SystemProfiler.uname
614
+ end
615
+ end
616
+
617
+ context "#uname_from_system" do
618
+ should "run without failure" do
619
+ # as above, just verify that an exception is not thrown
620
+ _ = TelnyxClient::SystemProfiler.uname_from_system
621
+ end
622
+ end
623
+
624
+ context "#uname_from_system_ver" do
625
+ should "run without failure" do
626
+ # as above, just verify that an exception is not thrown
627
+ _ = TelnyxClient::SystemProfiler.uname_from_system_ver
628
+ end
629
+ end
630
+ end
631
+ end