telnyx 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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