mock-twilio 0.7.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +32 -1
  4. data/lib/mock/twilio/decorator.rb +10 -2
  5. data/lib/mock/twilio/decorators/api_2010/calls.rb +11 -7
  6. data/lib/mock/twilio/decorators/api_2010/messages.rb +14 -1
  7. data/lib/mock/twilio/decorators/customer_profiles_v1/customer_profile.rb +1 -5
  8. data/lib/mock/twilio/decorators/customer_profiles_v1/customer_profile_update.rb +43 -0
  9. data/lib/mock/twilio/decorators/customer_profiles_v1/evaluations.rb +0 -4
  10. data/lib/mock/twilio/decorators/messaging_v1/phone_number_create.rb +42 -0
  11. data/lib/mock/twilio/decorators/messaging_v1/phone_number_fetch.rb +42 -0
  12. data/lib/mock/twilio/decorators/messaging_v1/phone_number_list.rb +43 -0
  13. data/lib/mock/twilio/decorators/trust_products_v1/entity_assignments.rb +35 -0
  14. data/lib/mock/twilio/decorators/trust_products_v1/evaluations.rb +37 -0
  15. data/lib/mock/twilio/decorators/trust_products_v1/trust_products.rb +35 -0
  16. data/lib/mock/twilio/decorators/trust_products_v1/update.rb +32 -0
  17. data/lib/mock/twilio/schemas/brands_registrations_a2p.rb +48 -0
  18. data/lib/mock/twilio/schemas/customer_profiles_v1.rb +5 -1
  19. data/lib/mock/twilio/schemas/messaging_v1.rb +17 -25
  20. data/lib/mock/twilio/schemas/trust_products_v1.rb +38 -0
  21. data/lib/mock/twilio/util/error_handler.rb +17 -0
  22. data/lib/mock/twilio/util/generator.rb +11 -0
  23. data/lib/mock/twilio/version.rb +1 -1
  24. data/lib/mock/twilio/webhooks/brands.rb +60 -0
  25. data/lib/mock/twilio/webhooks/call_status_updates.rb +1 -1
  26. data/lib/mock/twilio/webhooks/calls.rb +1 -1
  27. data/lib/mock/twilio/webhooks/conferences.rb +1 -1
  28. data/lib/mock/twilio/webhooks/customer_profiles.rb +1 -1
  29. data/lib/mock/twilio/webhooks/inbound_messages.rb +65 -0
  30. data/lib/mock/twilio/webhooks/messages.rb +1 -1
  31. data/lib/mock/twilio.rb +4 -0
  32. metadata +17 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58f6856b33391f0b81aebc0c46347bd74394f562566def73e8a3dbf7e7cc02f4
4
- data.tar.gz: 3315b80f6a87db016d88fafdabd02154363b4bc597063d99441f87904a923fd0
3
+ metadata.gz: 1da1ec05dd743344d3013c3f39a42923a3169f1712f5888379d404d29c437f0f
4
+ data.tar.gz: 59529b53405a1ea90813af0d41174a98a197a19c05b1b38968883e98fb7c8284
5
5
  SHA512:
6
- metadata.gz: ee811c5534f9cb9083f9a2f96156e12871003ed27a2c8303bbb311035937d70b36e4f08fa4fb68463ac0164e9a318d704841bcd58df11e21874d67b6bd7bde4a
7
- data.tar.gz: d3eb04ea5ccc63452acf17ebf3ec620c14faca67dc5a0b650834d963ae962b9be3b0d4884b2ae2e9c39191ddf2c509bd321d540a80c69cd5bfe6d4cb54e718bb
6
+ metadata.gz: 5663f1c128513d140c75d2505c85e1e77c71c226889d1aa3a230df2764f7d4010964f2781c895508c5a2eb3df2d60225aa7f74e64df1c3d0e6583e5fff4e8659
7
+ data.tar.gz: 07ef35f9b4ee075fb4af82ffb03e02b5e6bb4af1dc9d324c9a0c4de7590a4c29314c58933798ab53bc0bd3859bdec6410c6d506eb03171207381b343467b90ac
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [1.0.0] - 2024-08-06
2
+ - Support Webhooks::InboundMessages
3
+
4
+ ## [0.8.0] - 2024-07-24
5
+ - Support BrandsRegistratiosA2p
6
+ - Support A2pTrustProduct
7
+ - Support MessagingV1 PhoneNumbers
8
+ - Add ErrorHandler for rufus-scheduler
9
+
1
10
  ## [0.7.2] - 2024-07-11
2
11
  - Add PhoneNumberList default limit 1 only on Mock
3
12
 
data/README.md CHANGED
@@ -26,6 +26,38 @@ OR
26
26
  - `proxy_port = 4010`
27
27
  - `proxy_protocol = http`
28
28
 
29
+ ## Features Support
30
+
31
+ | Mock::Twilio::Client | Support |
32
+ | ------------- | ------------- |
33
+ | `client.messages.create(to: "+593978613041", body: "Testing SMS", from: "+13212855389")` | :white_check_mark: |
34
+ | `client.messaging.v1.services("MG"+"F"*32).phone_numbers.create(phone_number_sid: @phone_number_sid)` | :white_check_mark: |
35
+ | `client.available_phone_numbers('US').local.list(limit: 20)` | :white_check_mark: |
36
+ | `client.incoming_phone_numbers.create(phone_number: "+1987654321", voice_url: "#{BASE_URL}/api/v1/twilio_calls/incoming", sms_url: "#{BASE_URL}/api/v1/twilio_requests/inbound")` | :white_check_mark: |
37
+ | `client.lookups.v2.phone_numbers("+14159929960").fetch(fields: :line_type_intelligence)` | :white_check_mark: |
38
+ | `client.calls.create(url: '<http://demo.twilio.com/docs/voice.xml>', to: '+14155551212', from: '+15017122661', status_callback: '<https://myapp.com/events>', status_callback_event: ['ringing'], status_callback_method: 'POST')` | :white_check_mark: |
39
+ | `client.conferences("CF"+("F")*32).participants.create(label: 'customer', early_media: true, beep: 'onEnter', status_callback: '<https://myapp.com/events>', status_callback_event: ['ringing'], record: true, from: '+15017122661', to: '+15558675310')` | :white_check_mark: |
40
+ | `client.trusthub.v1.customer_profiles.create(**twilio_attributes)` | :white_check_mark: |
41
+ | `client.trusthub.v1.customer_profiles(customer_profile_sid).customer_profiles_entity_assignments.create(object_sid:)` | :white_check_mark: |
42
+ | `client.trusthub.v1.end_users.create(**twilio_parameters)` | :white_check_mark: |
43
+ | `client.trusthub.v1.supporting_documents.create(**twilio_parameters)` | :white_check_mark: |
44
+ | `client.addresses.create(**twilio_parameters)` | :white_check_mark: |
45
+ | `client.trusthub.v1.customer_profiles.create(**twilio_attributes)` | :white_check_mark: |
46
+ | `client.trusthub.v1.customer_profiles(customer_profile.sid).customer_profiles_evaluations.create(policy_sid:)` | :white_check_mark: |
47
+
48
+
49
+ ## Trigger resources updates
50
+
51
+ | Mock::Twilio::Webhooks | Support |
52
+ | ------------- | ------------- |
53
+ | `Webhooks::Messages` | :white_check_mark: |
54
+ | `Webhooks::InboundMessages` | :white_check_mark: |
55
+ | `Webhooks::Calls` | :white_check_mark: |
56
+ | `Webhooks::CallStatusUpdates` | :white_check_mark: |
57
+ | `Webhooks::Conferences` | :white_check_mark: |
58
+ | `Webhooks::CustomerProfiles` | :white_check_mark: |
59
+ | `Webhooks::Brands` | :white_check_mark: |
60
+
29
61
  ## How to use
30
62
  Initializer sample
31
63
  ```ruby
@@ -35,7 +67,6 @@ Mock::Twilio.configure do |config|
35
67
  config.port = "3000"
36
68
  config.proto = "http"
37
69
  end
38
-
39
70
  ```
40
71
 
41
72
  Example
@@ -6,6 +6,8 @@ require_relative "schemas/customer_profiles_v1"
6
6
  require_relative "schemas/end_users_v1"
7
7
  require_relative "schemas/supporting_documents_v1"
8
8
  require_relative "schemas/phone_numbers_v2"
9
+ require_relative "schemas/brands_registrations_a2p"
10
+ require_relative "schemas/trust_products_v1"
9
11
 
10
12
  module Mock
11
13
  module Twilio
@@ -16,7 +18,9 @@ module Mock
16
18
  customer_profiles_v1: Mock::Twilio::Schemas::CustomerProfilesV1,
17
19
  end_users_v1: Mock::Twilio::Schemas::EndUsersV1,
18
20
  supporting_documents_v1: Mock::Twilio::Schemas::SupportingDocumentsV1,
19
- phone_numbers_v2: Mock::Twilio::Schemas::PhoneNumbersV2
21
+ phone_numbers_v2: Mock::Twilio::Schemas::PhoneNumbersV2,
22
+ brands_registrations_a2p: Mock::Twilio::Schemas::BrandsRegistrationsA2p,
23
+ trust_products_v1: Mock::Twilio::Schemas::TrustProductsV1
20
24
  }
21
25
 
22
26
  class << self
@@ -41,7 +45,7 @@ module Mock
41
45
  case url
42
46
  when %r{\/2010-04-01/Accounts/[A-Za-z0-9]+/}
43
47
  :api_2010
44
- when %r{\/v1/Services/[A-Za-z0-9]+/}
48
+ when %r{\/v1\/Services\/\w{34}}
45
49
  :messaging_v1
46
50
  when %r{\/v1/CustomerProfiles}
47
51
  :customer_profiles_v1
@@ -51,6 +55,10 @@ module Mock
51
55
  :supporting_documents_v1
52
56
  when %r{\/v2/PhoneNumbers}
53
57
  :phone_numbers_v2
58
+ when %r{\/v1/a2p/BrandRegistrations}
59
+ :brands_registrations_a2p
60
+ when %r{\/v1/TrustProducts}
61
+ :trust_products_v1
54
62
  end
55
63
  end
56
64
  end
@@ -29,15 +29,19 @@ module Mock
29
29
  scheduler = Rufus::Scheduler.new
30
30
  scheduler.in '2s' do
31
31
  conference_uuid = request.data["Url"].split("conference_uuid=").last
32
- response = Mock::Twilio::Webhooks::CallStatusUpdates.trigger(sid, conference_uuid)
32
+ begin
33
+ response = Mock::Twilio::Webhooks::CallStatusUpdates.trigger(sid, conference_uuid)
33
34
 
34
- conference_response = if response.status == 200
35
- twiMl_xml = Nokogiri::XML response.body
36
- friendly_name = twiMl_xml.at_xpath('//Dial').at_xpath('//Conference').children.text
37
- Mock::Twilio::Webhooks::Conferences.trigger(friendly_name)
38
- end
35
+ conference_response = if response.status == 200
36
+ twiMl_xml = Nokogiri::XML response.body
37
+ friendly_name = twiMl_xml.at_xpath('//Dial').at_xpath('//Conference').children.text
38
+ Mock::Twilio::Webhooks::Conferences.trigger(friendly_name)
39
+ end
39
40
 
40
- Mock::Twilio::Webhooks::Calls.trigger(sid) if conference_response.status == 200
41
+ Mock::Twilio::Webhooks::Calls.trigger(sid) if conference_response.status == 200
42
+ rescue => e
43
+ puts e
44
+ end
41
45
  end
42
46
  body["sid"] = sid
43
47
  end
@@ -14,8 +14,12 @@ module Mock
14
14
  body["end_time"] = Time.current.rfc2822 if body["end_time"]
15
15
 
16
16
  message_sid(body, request) if body["sid"]
17
+ body["messaging_service_sid"] = request.data["MessagingServiceSid"] if request.data["MessagingServiceSid"]
17
18
  pagination(body) if body["available_phone_numbers"]
18
19
 
20
+ body["to"] = request.data["To"] if request.data["To"]
21
+ body["from"] = request.data["From"] if request.data["From"]
22
+
19
23
  body
20
24
  end
21
25
 
@@ -32,7 +36,16 @@ module Mock
32
36
  sid = prefix + SecureRandom.hex(16)
33
37
  scheduler = Rufus::Scheduler.new
34
38
  scheduler.in '2s' do
35
- Mock::Twilio::Webhooks::Messages.trigger(sid)
39
+ begin
40
+ response = Mock::Twilio::Webhooks::Messages.trigger(sid)
41
+
42
+ if response.success? && request.data["Body"].downcase.include?("inbound")
43
+ inbound_sid = prefix + SecureRandom.hex(16)
44
+ Mock::Twilio::Webhooks::InboundMessages.trigger(inbound_sid, request.data)
45
+ end
46
+ rescue => e
47
+ puts e
48
+ end
36
49
  end
37
50
  body["sid"] = sid
38
51
  end
@@ -15,7 +15,7 @@ module Mock
15
15
  body["email"] = request.data["Email"] if body["email"]
16
16
  body["policy_sid"] = request.data["PolicySid"] if body["policy_sid"]
17
17
  body["status_callback"] = request.data["StatusCallback"] if body["status_callback"]
18
- body["status"] = "in-review" if body["status"]
18
+ body["status"] = "draft" if body["status"]
19
19
 
20
20
  body
21
21
  end
@@ -23,10 +23,6 @@ module Mock
23
23
  def customer_profile_sid(body, request)
24
24
  prefix = "BU"
25
25
  sid = prefix + SecureRandom.hex(16)
26
- scheduler = Rufus::Scheduler.new
27
- scheduler.in '2s' do
28
- Mock::Twilio::Webhooks::CustomerProfiles.trigger(sid, "in-review")
29
- end
30
26
  body["sid"] = sid
31
27
  end
32
28
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module CustomerProfilesV1
7
+ class CustomerProfileUpdate
8
+ class << self
9
+ def decorate(body, request)
10
+ body["date_updated"] = Time.current.rfc2822 if body["date_updated"]
11
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
12
+
13
+ parse_customer_profile_sid(body, request) if body["sid"]
14
+ body["account_sid"] = ::Twilio.account_sid if body["account_sid"]
15
+ # Usually from pending-review to in-review
16
+ body["status"] = request.data["Status"] if body["status"]
17
+
18
+ body
19
+ end
20
+
21
+ def parse_customer_profile_sid(body, request)
22
+ uri = URI(request.url)
23
+ customer_profile_sid = uri.path.split('/')[3].split('.').first
24
+ scheduler = Rufus::Scheduler.new
25
+ scheduler.in '2s' do
26
+ begin
27
+ response = Mock::Twilio::Webhooks::CustomerProfiles.trigger(customer_profile_sid, "in-review")
28
+
29
+ if response.status == 200
30
+ Mock::Twilio::Webhooks::CustomerProfiles.trigger(customer_profile_sid, "twilio-approved")
31
+ end
32
+ rescue => e
33
+ puts e
34
+ end
35
+ end
36
+ body["sid"] = customer_profile_sid
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -20,10 +20,6 @@ module Mock
20
20
  def evaluation_sid(body, request)
21
21
  prefix = "EL"
22
22
  sid = prefix + SecureRandom.hex(16)
23
- scheduler = Rufus::Scheduler.new
24
- scheduler.in '2s' do
25
- Mock::Twilio::Webhooks::CustomerProfiles.trigger(body['customer_profile_sid'], "twilio-approved")
26
- end
27
23
  body["sid"] = sid
28
24
  end
29
25
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module MessagingV1
7
+ class PhoneNumberCreate
8
+ class << self
9
+ include Mock::Twilio::Generator
10
+
11
+ def decorate(body, request)
12
+ body["date_updated"] = Time.current.rfc2822 if body["date_updated"]
13
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
14
+
15
+ phone_number_sid(body) if body["sid"]
16
+ parse_messaging_service_sid(body, request) if body["service_sid"]
17
+
18
+ body["account_sid"] = ::Twilio.account_sid if body["account_sid"]
19
+ body["country_code"] = "US" if body["country_code"]
20
+ body["capabilities"] = [] if body["capabilities"]
21
+ body["phone_number"] = phone_number_generator if body["phone_number"]
22
+
23
+ body
24
+ end
25
+
26
+ def phone_number_sid(body)
27
+ prefix = "PN"
28
+ sid = prefix + SecureRandom.hex(16)
29
+ body["sid"] = sid
30
+ end
31
+
32
+ def parse_messaging_service_sid(body, request)
33
+ uri = URI(request.url)
34
+ messaging_service_sid = uri.path.split('/')[3]
35
+ body["service_sid"] = messaging_service_sid
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module MessagingV1
7
+ class PhoneNumberFetch
8
+ class << self
9
+ include Mock::Twilio::Generator
10
+
11
+ def decorate(body, request)
12
+ body["date_updated"] = Time.current.rfc2822 if body["date_updated"]
13
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
14
+
15
+ parse_messaging_phone_number_sid(body, request) if body["sid"]
16
+ parse_messaging_service_sid(body, request) if body["service_sid"]
17
+
18
+ body["account_sid"] = ::Twilio.account_sid if body["account_sid"]
19
+ body["country_code"] = "US" if body["country_code"]
20
+ body["capabilities"] = [] if body["capabilities"]
21
+ body["phone_number"] = phone_number_generator if body["phone_number"]
22
+
23
+ body
24
+ end
25
+
26
+ def parse_messaging_phone_number_sid(body, request)
27
+ uri = URI(request.url)
28
+ phone_number_sid = uri.path.split('/')[5]
29
+ body["sid"] = phone_number_sid
30
+ end
31
+
32
+ def parse_messaging_service_sid(body, request)
33
+ uri = URI(request.url)
34
+ messaging_service_sid = uri.path.split('/')[3]
35
+ body["service_sid"] = messaging_service_sid
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module MessagingV1
7
+ class PhoneNumberList
8
+ class << self
9
+ def decorate(body, request)
10
+ phone_number_sid(body) if body["phone_numbers"].first["sid"]
11
+ body["phone_numbers"].first["account_sid"] = ::Twilio.account_sid if body["phone_numbers"].first["account_sid"]
12
+ parse_messaging_service_sid(body, request) if body["phone_numbers"].first["service_sid"]
13
+ body["phone_numbers"].first["phone_number"] = "+19876543210" if body["phone_numbers"].first["phone_number"]
14
+ body["phone_numbers"].first["country_code"] = "US" if body["phone_numbers"].first["country_code"]
15
+
16
+ # Params for twilio pagination, needed for twilio-ruby serializers and absolute paths
17
+ body["meta"]["key"] = "phone_numbers" if body["meta"]["key"]
18
+ body["meta"]["page_size"] = 20 if body["meta"]["page_size"]
19
+ body["meta"]["first_page_url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=0" if body["meta"]["first_page_url"]
20
+ body["meta"]["previous_page_url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=0" if body["meta"]["previous_page_url"]
21
+ body["meta"]["next_page_url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=1" if body["meta"]["next_page_url"]
22
+ body["meta"]["url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=0" if body["meta"]["url"]
23
+
24
+ body
25
+ end
26
+
27
+ def phone_number_sid(body)
28
+ prefix = "PN"
29
+ sid = prefix + SecureRandom.hex(16)
30
+ body["phone_numbers"].first["sid"] = sid
31
+ end
32
+
33
+ def parse_messaging_service_sid(body, request)
34
+ uri = URI(request.url)
35
+ messaging_service_sid = uri.path.split('/')[3]
36
+ body["phone_numbers"].first["service_sid"] = messaging_service_sid
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module TrustProductsV1
7
+ class EntityAssignments
8
+ class << self
9
+ def decorate(body, request)
10
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
11
+ entity_sid(body, request) if body["sid"]
12
+ body["account_sid"] = ::Twilio.account_sid
13
+ body["object_sid"] = request.data["ObjectSid"]
14
+ parse_trust_product_sid(body, request) if body["trust_product_sid"]
15
+
16
+ body
17
+ end
18
+
19
+ def entity_sid(body, request)
20
+ prefix = "BV"
21
+ sid = prefix + SecureRandom.hex(16)
22
+ body["sid"] = sid
23
+ end
24
+
25
+ def parse_trust_product_sid(body, request)
26
+ uri = URI(request.url)
27
+ trust_product_sid = uri.path.split('/')[3].split('.').first
28
+ body["trust_product_sid"] = trust_product_sid
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module TrustProductsV1
7
+ class Evaluations
8
+ class << self
9
+ def decorate(body, request)
10
+ parse_trust_product_sid(body, request) if body["trust_product_sid"]
11
+ evaluation_sid(body) if body["sid"]
12
+
13
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
14
+ body["account_sid"] = ::Twilio.account_sid
15
+ body["policy_sid"] = request.data["PolicySid"] if body["policy_sid"]
16
+ body["status"] = "compliant" if body["status"]
17
+
18
+ body
19
+ end
20
+
21
+ def evaluation_sid(body)
22
+ prefix = "EL"
23
+ sid = prefix + SecureRandom.hex(16)
24
+ body["sid"] = sid
25
+ end
26
+
27
+ def parse_trust_product_sid(body, request)
28
+ uri = URI(request.url)
29
+ trust_product_sid = uri.path.split('/')[3].split('.').first
30
+ body["trust_product_sid"] = trust_product_sid
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module TrustProductsV1
7
+ class TrustProducts
8
+ class << self
9
+ def decorate(body, request)
10
+ body["date_updated"] = Time.current.rfc2822 if body["date_updated"]
11
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
12
+
13
+ trust_product_sid(body) if body["sid"]
14
+ body["account_sid"] = ::Twilio.account_sid if body["account_sid"]
15
+
16
+ body["friendly_name"] = request.data["FriendlyName"] if body["friendly_name"]
17
+ body["email"] = request.data["Email"] if body["email:"]
18
+ body["policy_sid"] = request.data["PolicySid"] if body["policy_sid"]
19
+ body["status"] = "draft" if body["status"]
20
+ body["valid_until"] = nil if body["valid_until"]
21
+
22
+ body
23
+ end
24
+
25
+ def trust_product_sid(body)
26
+ prefix = "BU"
27
+ sid = prefix + SecureRandom.hex(16)
28
+ body["sid"] = sid
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Decorators
6
+ module TrustProductsV1
7
+ class Update
8
+ class << self
9
+ def decorate(body, request)
10
+ body["date_updated"] = Time.current.rfc2822 if body["date_updated"]
11
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
12
+
13
+ trust_product_sid(body) if body["sid"]
14
+ body["account_sid"] = ::Twilio.account_sid if body["account_sid"]
15
+
16
+ body["status"] = request.data["Status"] if body["status"]
17
+ body["valid_until"] = nil if body["valid_until"]
18
+
19
+ body
20
+ end
21
+
22
+ def trust_product_sid(body)
23
+ prefix = "BU"
24
+ sid = prefix + SecureRandom.hex(16)
25
+ body["sid"] = sid
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Schemas
6
+ class BrandsRegistrationsA2p
7
+ class << self
8
+ def for(body, request)
9
+ body["date_updated"] = Time.current.rfc2822 if body["date_updated"]
10
+ body["date_created"] = Time.current.rfc2822 if body["date_created"]
11
+
12
+ brand_sid(body) if body["sid"]
13
+ body["account_sid"] = ::Twilio.account_sid if body["account_sid"]
14
+ body["customer_profile_bundle_sid"] = request.data["CustomerProfileBundleSid"] if body["customer_profile_bundle_sid"]
15
+ body["a2p_profile_bundle_sid"] = request.data["A2PProfileBundleSid"] if body["a2p_profile_bundle_sid"]
16
+ body["brand_type"] = request.data["BrandType"] if body["brand_type"]
17
+ body["account_sid"] = ::Twilio.account_sid if body["account_sid"]
18
+
19
+ body["status"] = "PENDING" if body["status"]
20
+ body["brand_score"] = 100 if body["brand_score"]
21
+ body["identity_status"] = "SELF_DECLARED" if body["identity_status"]
22
+ body["tcr_id"] = "BXXXXXX" if body["tcr_id"]
23
+ body["tax_exempt_status"] = "501c3" if body["tax_exempt_status"]
24
+
25
+ body["errors"] = nil if body["errors"]
26
+ body["failure_reason"] = nil if body["failure_reason"]
27
+ body["links"] = { "brand_vettings": "http://example.com", "brand_registration_otps": "http://example.com" } if body["links"]
28
+
29
+ body
30
+ end
31
+
32
+ def brand_sid(body)
33
+ prefix = "BN"
34
+ sid = prefix + SecureRandom.hex(16)
35
+ scheduler = Rufus::Scheduler.new
36
+ scheduler.in '2s' do
37
+ response = Mock::Twilio::Webhooks::Brands.trigger(sid, "unverified")
38
+ response = if response.status == 200
39
+ Mock::Twilio::Webhooks::Brands.trigger(sid, "verified")
40
+ end
41
+ end
42
+ body["sid"] = sid
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -3,6 +3,7 @@
3
3
  require_relative "../decorators/customer_profiles_v1/customer_profile"
4
4
  require_relative "../decorators/customer_profiles_v1/entity_assignments"
5
5
  require_relative "../decorators/customer_profiles_v1/evaluations"
6
+ require_relative "../decorators/customer_profiles_v1/customer_profile_update"
6
7
 
7
8
  module Mock
8
9
  module Twilio
@@ -12,7 +13,8 @@ module Mock
12
13
  RESOURCES = {
13
14
  customer_profile: Mock::Twilio::Decorators::CustomerProfilesV1::CustomerProfile,
14
15
  entity_assigments: Mock::Twilio::Decorators::CustomerProfilesV1::EntityAssignments,
15
- evaluations: Mock::Twilio::Decorators::CustomerProfilesV1::Evaluations
16
+ evaluations: Mock::Twilio::Decorators::CustomerProfilesV1::Evaluations,
17
+ customer_profile_update: Mock::Twilio::Decorators::CustomerProfilesV1::CustomerProfileUpdate,
16
18
  }
17
19
 
18
20
  def for(body, request)
@@ -25,6 +27,8 @@ module Mock
25
27
  RESOURCES[:entity_assigments].decorate(body, request)
26
28
  when %r{\/v1/CustomerProfiles/[A-Za-z0-9]+/Evaluations}
27
29
  RESOURCES[:evaluations].decorate(body, request)
30
+ when %r{\/v1/CustomerProfiles/[A-Za-z0-0]+}
31
+ RESOURCES[:customer_profile_update].decorate(body, request)
28
32
  end
29
33
  end
30
34
  end
@@ -1,37 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../decorators/messaging_v1/phone_number_list"
4
+ require_relative "../decorators/messaging_v1/phone_number_create"
5
+ require_relative "../decorators/messaging_v1/phone_number_fetch"
6
+
3
7
  module Mock
4
8
  module Twilio
5
9
  module Schemas
6
10
  class MessagingV1
7
11
  class << self
12
+ RESOURCES = {
13
+ phone_number_list: Mock::Twilio::Decorators::MessagingV1::PhoneNumberList,
14
+ phone_number_create: Mock::Twilio::Decorators::MessagingV1::PhoneNumberCreate,
15
+ phone_number_fetch: Mock::Twilio::Decorators::MessagingV1::PhoneNumberFetch,
16
+ }
8
17
  def for(body, request)
9
- phone_number_sid(body) if body["phone_numbers"].first["sid"]
10
- body["phone_numbers"].first["account_sid"] = ::Twilio.account_sid if body["phone_numbers"].first["account_sid"]
11
- parse_messaging_service_sid(body, request) if body["phone_numbers"].first["service_sid"]
12
- body["phone_numbers"].first["phone_number"] = "+19876543210" if body["phone_numbers"].first["phone_number"]
13
- body["phone_numbers"].first["country_code"] = "US" if body["phone_numbers"].first["country_code"]
14
-
15
- # Params for twilio pagination, needed for twilio-ruby serializers and absolute paths
16
- body["meta"]["key"] = "phone_numbers" if body["meta"]["key"]
17
- body["meta"]["page_size"] = 20 if body["meta"]["page_size"]
18
- body["meta"]["first_page_url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=0" if body["meta"]["first_page_url"]
19
- body["meta"]["previous_page_url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=0" if body["meta"]["previous_page_url"]
20
- body["meta"]["next_page_url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=1" if body["meta"]["next_page_url"]
21
- body["meta"]["url"] = "https://messaging.twilio.com/v1/Services/MGFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/PhoneNumbers?PageSize=20&Page=0" if body["meta"]["url"]
22
- body
23
- end
24
-
25
- def phone_number_sid(body)
26
- prefix = "PN"
27
- sid = prefix + SecureRandom.hex(16)
28
- body["phone_numbers"].first["sid"] = sid
29
- end
18
+ url = request.url.split(request.host).last
30
19
 
31
- def parse_messaging_service_sid(body, request)
32
- uri = URI(request.url)
33
- messaging_service_sid = uri.path.split('/')[3]
34
- body["phone_numbers"].first["service_sid"] = messaging_service_sid
20
+ case url
21
+ when %r{\/v1\/Services\/\w{34}\/PhoneNumbers$}
22
+ return RESOURCES[:phone_number_list].decorate(body, request) if request.method == "GET"
23
+ return RESOURCES[:phone_number_create].decorate(body, request) if request.method == "POST"
24
+ when %r{\/v1\/Services\/\w{34}\/PhoneNumbers\/\w{34}}
25
+ RESOURCES[:phone_number_fetch].decorate(body, request)
26
+ end
35
27
  end
36
28
  end
37
29
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../decorators/trust_products_v1/trust_products"
4
+ require_relative "../decorators/trust_products_v1/update"
5
+ require_relative "../decorators/trust_products_v1/evaluations"
6
+ require_relative "../decorators/trust_products_v1/entity_assignments"
7
+
8
+ module Mock
9
+ module Twilio
10
+ module Schemas
11
+ class TrustProductsV1
12
+ class << self
13
+ RESOURCES = {
14
+ trust_products: Mock::Twilio::Decorators::TrustProductsV1::TrustProducts,
15
+ update: Mock::Twilio::Decorators::TrustProductsV1::Update,
16
+ evaluations: Mock::Twilio::Decorators::TrustProductsV1::Evaluations,
17
+ entity_assignments: Mock::Twilio::Decorators::TrustProductsV1::EntityAssignments,
18
+ }
19
+
20
+ def for(body, request)
21
+ url = request.url.split(request.host).last
22
+
23
+ case url
24
+ when %r{\/v1/TrustProducts$}
25
+ RESOURCES[:trust_products].decorate(body, request)
26
+ when %r{\/v1/TrustProducts/\w{34}$}
27
+ RESOURCES[:update].decorate(body, request)
28
+ when %r{\/v1\/TrustProducts\/\w{34}\/Evaluations$}
29
+ RESOURCES[:evaluations].decorate(body, request)
30
+ when %r{\/v1\/TrustProducts\/\w{34}\/EntityAssignments$}
31
+ RESOURCES[:entity_assignments].decorate(body, request)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ class ErrorHandler
6
+ def initialize(response)
7
+ @response = response
8
+ end
9
+
10
+ def raise
11
+ return @response.body if @response.headers["content-type"].include?("application/json")
12
+
13
+ @response.reason_phrase
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Generator
6
+ def phone_number_generator
7
+ "+1" + rand(100000000..999999999).to_s
8
+ end
9
+ end
10
+ end
11
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Mock
4
4
  module Twilio
5
- VERSION = "0.7.2"
5
+ VERSION = "1.0.0"
6
6
  end
7
7
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Webhooks
6
+ class Brands < Base
7
+ URL = "/webhooks/twilio/brands_compliance"
8
+ EVENTS = { "verified": "registered", "unverified": "unverified" }
9
+
10
+ def self.trigger(sid, status)
11
+ # Wait simulation from twilio
12
+ sleep DELAY.sample
13
+
14
+ request_url = Mock::Twilio.proto + "://" + Mock::Twilio.forwarded_host + URL
15
+
16
+ data = data_builder(sid, status)
17
+
18
+ signature = build_signature_for_request(request_url, data)
19
+
20
+ response = webhook_client.request(Mock::Twilio.host,
21
+ Mock::Twilio.port,
22
+ 'POST',
23
+ URL,
24
+ nil,
25
+ data.to_json,
26
+ headers.merge!({ 'X-Twilio-Signature': signature, 'Content-Type': 'application/json' }),
27
+ auth_twilio,
28
+ nil)
29
+ case response.status
30
+ when 200..204
31
+ response
32
+ when 400..600
33
+ raise Webhooks::RestError, Mock::Twilio::ErrorHandler.new(response).raise
34
+ end
35
+ end
36
+
37
+ def self.data_builder(sid, status)
38
+ uuid = SecureRandom.uuid
39
+ type = status
40
+ [
41
+ {
42
+ specversion: "1.0",
43
+ type: "com.twilio.messaging.compliance.brand-registration.brand-" + EVENTS[status.to_sym],
44
+ source: uuid,
45
+ id: uuid,
46
+ datacontenttype: "application/json",
47
+ time: Time.current.rfc2822,
48
+ data: {
49
+ accountsid: ::Twilio.account_sid,
50
+ brandsid: sid,
51
+ brandstatus: "registered",
52
+ identitystatus: status
53
+ }
54
+ }
55
+ ]
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -29,7 +29,7 @@ module Mock
29
29
  when 200..204
30
30
  response
31
31
  when 400..600
32
- raise Webhooks::RestError, response.body
32
+ raise Webhooks::RestError, Mock::Twilio::ErrorHandler.new(response).raise
33
33
  end
34
34
  end
35
35
 
@@ -29,7 +29,7 @@ module Mock
29
29
  when 200..204
30
30
  response
31
31
  when 400..600
32
- raise Webhooks::RestError, response.body
32
+ raise Webhooks::RestError, Mock::Twilio::ErrorHandler.new(response).raise
33
33
  end
34
34
  end
35
35
 
@@ -30,7 +30,7 @@ module Mock
30
30
  when 200..204
31
31
  response
32
32
  when 400..600
33
- raise Webhooks::RestError, response.body
33
+ raise Webhooks::RestError, Mock::Twilio::ErrorHandler.new(response).raise
34
34
  end
35
35
  end
36
36
 
@@ -29,7 +29,7 @@ module Mock
29
29
  when 200..204
30
30
  response
31
31
  when 400..600
32
- raise Webhooks::RestError, response.body
32
+ raise Webhooks::RestError, Mock::Twilio::ErrorHandler.new(response).raise
33
33
  end
34
34
  end
35
35
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mock
4
+ module Twilio
5
+ module Webhooks
6
+ class InboundMessages < Base
7
+ URL = "/api/v1/twilio_requests/inbound"
8
+
9
+ def self.trigger(sid, params)
10
+ raise Webhooks::RestError, "Invalid Inbound message data" if params['To'].empty? || params['From'].empty?
11
+ # Wait simulation from twilio
12
+ sleep DELAY.sample
13
+
14
+ request_url = Mock::Twilio.proto + "://" + Mock::Twilio.forwarded_host + URL
15
+
16
+ data = inbound_data(sid, params)
17
+
18
+ signature = build_signature_for_request(request_url, data)
19
+
20
+ response = webhook_client.request(Mock::Twilio.host,
21
+ Mock::Twilio.port,
22
+ 'POST',
23
+ URL,
24
+ nil,
25
+ data,
26
+ headers.merge!({ 'X-Twilio-Signature': signature }),
27
+ auth_twilio,
28
+ nil)
29
+ case response.status
30
+ when 200..204
31
+ response
32
+ when 400..600
33
+ raise Webhooks::RestError, Mock::Twilio::ErrorHandler.new(response).raise
34
+ end
35
+ end
36
+
37
+ def self.inbound_data(sid, params)
38
+ {
39
+ "ToCountry": "US",
40
+ "ToState": "MS",
41
+ "SmsMessageSid": sid,
42
+ "NumMedia": "0",
43
+ "ToCity": "SARDIS",
44
+ "FromZip": "98315",
45
+ "SmsSid": sid,
46
+ "FromState": "WA",
47
+ "SmsStatus": "received",
48
+ "FromCity": "SILVERDALE",
49
+ "Body": "Inbound::Message mock reply",
50
+ "FromCountry": "US",
51
+ "To": params["To"],
52
+ "MessagingServiceSid": params['MessagingServiceSid'],
53
+ "ToZip": "38666",
54
+ "AddOns": "{\"status\":\"successful\",\"message\":null,\"code\":null,\"results\":{}}",
55
+ "NumSegments": "1",
56
+ "MessageSid": sid,
57
+ "AccountSid": ::Twilio.account_sid,
58
+ "From": params["From"],
59
+ "ApiVersion": "2010-04-01"
60
+ }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -29,7 +29,7 @@ module Mock
29
29
  when 200..204
30
30
  response
31
31
  when 400..600
32
- raise Webhooks::RestError, response.body
32
+ raise Webhooks::RestError, Mock::Twilio::ErrorHandler.new(response).raise
33
33
  end
34
34
  end
35
35
  end
data/lib/mock/twilio.rb CHANGED
@@ -12,7 +12,11 @@ require_relative "twilio/webhooks/calls"
12
12
  require_relative "twilio/webhooks/call_status_updates"
13
13
  require_relative "twilio/webhooks/conferences"
14
14
  require_relative "twilio/webhooks/customer_profiles"
15
+ require_relative "twilio/webhooks/brands"
16
+ require_relative "twilio/webhooks/inbound_messages"
15
17
  require_relative "twilio/util/configuration"
18
+ require_relative "twilio/util/error_handler"
19
+ require_relative "twilio/util/generator"
16
20
  require_relative "twilio/client"
17
21
  require_relative "twilio/decorator"
18
22
  require_relative "twilio/response"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mock-twilio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SchoolStatus Platform Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-12 00:00:00.000000000 Z
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -86,24 +86,38 @@ files:
86
86
  - lib/mock/twilio/decorators/api_2010/conferences_participants_update.rb
87
87
  - lib/mock/twilio/decorators/api_2010/messages.rb
88
88
  - lib/mock/twilio/decorators/customer_profiles_v1/customer_profile.rb
89
+ - lib/mock/twilio/decorators/customer_profiles_v1/customer_profile_update.rb
89
90
  - lib/mock/twilio/decorators/customer_profiles_v1/entity_assignments.rb
90
91
  - lib/mock/twilio/decorators/customer_profiles_v1/evaluations.rb
92
+ - lib/mock/twilio/decorators/messaging_v1/phone_number_create.rb
93
+ - lib/mock/twilio/decorators/messaging_v1/phone_number_fetch.rb
94
+ - lib/mock/twilio/decorators/messaging_v1/phone_number_list.rb
95
+ - lib/mock/twilio/decorators/trust_products_v1/entity_assignments.rb
96
+ - lib/mock/twilio/decorators/trust_products_v1/evaluations.rb
97
+ - lib/mock/twilio/decorators/trust_products_v1/trust_products.rb
98
+ - lib/mock/twilio/decorators/trust_products_v1/update.rb
91
99
  - lib/mock/twilio/middleware/proxy.rb
92
100
  - lib/mock/twilio/response.rb
93
101
  - lib/mock/twilio/schemas/api_2010.rb
102
+ - lib/mock/twilio/schemas/brands_registrations_a2p.rb
94
103
  - lib/mock/twilio/schemas/customer_profiles_v1.rb
95
104
  - lib/mock/twilio/schemas/end_users_v1.rb
96
105
  - lib/mock/twilio/schemas/messaging_v1.rb
97
106
  - lib/mock/twilio/schemas/phone_numbers_v2.rb
98
107
  - lib/mock/twilio/schemas/supporting_documents_v1.rb
108
+ - lib/mock/twilio/schemas/trust_products_v1.rb
99
109
  - lib/mock/twilio/util/configuration.rb
110
+ - lib/mock/twilio/util/error_handler.rb
111
+ - lib/mock/twilio/util/generator.rb
100
112
  - lib/mock/twilio/version.rb
101
113
  - lib/mock/twilio/webhook_client.rb
102
114
  - lib/mock/twilio/webhooks/base.rb
115
+ - lib/mock/twilio/webhooks/brands.rb
103
116
  - lib/mock/twilio/webhooks/call_status_updates.rb
104
117
  - lib/mock/twilio/webhooks/calls.rb
105
118
  - lib/mock/twilio/webhooks/conferences.rb
106
119
  - lib/mock/twilio/webhooks/customer_profiles.rb
120
+ - lib/mock/twilio/webhooks/inbound_messages.rb
107
121
  - lib/mock/twilio/webhooks/messages.rb
108
122
  - lib/twilio/rest/messaging/v1/service/phone_number_decorator.rb
109
123
  - sig/mock/twilio.rbs
@@ -132,5 +146,5 @@ requirements: []
132
146
  rubygems_version: 3.5.12
133
147
  signing_key:
134
148
  specification_version: 4
135
- summary: This repository contains Mock::Twilio::Client for Twilio's API.
149
+ summary: This repository contains Mock::Twilio::Client and Webhooks for Twilio's API.
136
150
  test_files: []