Merge branch 'import-to-catapult'

Stephen Paul Weber created

* import-to-catapult:
  Import newly-purchased numbers to Catapult

Change summary

.rubocop.yml                        |  4 ++
config.dhall.sample                 |  6 +++
lib/bandwidth_tn_order.rb           | 54 ++++++++++++++++++++++++++++++
test/data/catapult_import_body.json |  1 
test/test_bandwidth_tn_order.rb     | 34 +++++++++++++++++-
test/test_helper.rb                 |  6 +++
test/test_registration.rb           | 15 ++++++++
7 files changed, 116 insertions(+), 4 deletions(-)

Detailed changes

.rubocop.yml 🔗

@@ -6,6 +6,10 @@ Metrics/LineLength:
   Exclude:
     - Gemfile
 
+Metrics/ClassLength:
+  Exclude:
+    - test/*
+
 Metrics/MethodLength:
   Exclude:
     - test/*

config.dhall.sample 🔗

@@ -13,6 +13,12 @@
 		username = "dashboard user",
 		password = "dashboard password"
 	},
+	catapult = {
+		user = "",
+		token = "",
+		secret = "",
+		application_id = ""
+	},
 	bandwidth_site = "",
 	braintree = {
 		environment = "sandbox",

lib/bandwidth_tn_order.rb 🔗

@@ -70,8 +70,60 @@ class BandwidthTNOrder
 			:complete
 		end
 
+		def tel
+			"+1#{@order.completed_numbers[:telephone_number][:full_number]}"
+		end
+
 		def poll
-			EMPromise.resolve(self)
+			catapult_import.then do |http|
+				raise "Catapult import failed" unless http.response_header.status == 201
+
+				self
+			end
+		end
+
+	protected
+
+		# After buying, import to catapult and set v1 voice app
+		def catapult_import
+			catapult_request.apost(
+				head: catapult_headers,
+				body: {
+					number: tel,
+					applicationId: catapult[:application_id],
+					provider: dashboard_provider
+				}.to_json
+			)
+		end
+
+		def catapult
+			CONFIG[:catapult]
+		end
+
+		def catapult_request
+			EM::HttpRequest.new(
+				"https://api.catapult.inetwork.com/v1/users/" \
+				"#{catapult[:user]}/phoneNumbers",
+				tls: { verify_peer: true }
+			)
+		end
+
+		def catapult_headers
+			{
+				"Authorization" => [catapult[:token], catapult[:secret]],
+				"Content-Type" => "application/json"
+			}
+		end
+
+		def dashboard_provider
+			{
+				providerName: "bandwidth-dashboard",
+				properties: {
+					accountId: CONFIG[:creds][:account],
+					userName: CONFIG[:creds][:username],
+					password: CONFIG[:creds][:password]
+				}
+			}
 		end
 	end
 

test/data/catapult_import_body.json 🔗

@@ -0,0 +1 @@
+{"number":"+15555550000","applicationId":"catapult_app","provider":{"providerName":"bandwidth-dashboard","properties":{"accountId":"test_bw_account","userName":"test_bw_user","password":"test_bw_password"}}}

test/test_bandwidth_tn_order.rb 🔗

@@ -53,10 +53,23 @@ class BandwidthTNOrderTest < Minitest::Test
 			).to_return(status: 200, body: <<~RESPONSE)
 				<OrderResponse>
 					<OrderStatus>COMPLETE</OrderStatus>
+					<CompletedNumbers>
+						<TelephoneNumber>
+							<FullNumber>5555550000</FullNumber>
+						</TelephoneNumber>
+					</CompletedNumbers>
 				</OrderResponse>
 			RESPONSE
-			new_order = PromiseMock.new
-			new_order.expect(:poll, nil)
+			stub_request(
+				:post,
+				"https://api.catapult.inetwork.com/v1/users/catapult_user/phoneNumbers"
+			).with(
+				body: open(__dir__ + "/data/catapult_import_body.json").read.chomp,
+				headers: {
+					"Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0",
+					"Content-Type" => "application/json"
+				}
+			).to_return(status: 200)
 			@order.poll.sync
 			assert_requested req
 		end
@@ -65,11 +78,26 @@ class BandwidthTNOrderTest < Minitest::Test
 
 	class TestComplete < Minitest::Test
 		def setup
-			@order = BandwidthTNOrder::Complete.new(BandwidthIris::Order.new)
+			@order = BandwidthTNOrder::Complete.new(BandwidthIris::Order.new(
+				completed_numbers: {
+					telephone_number: { full_number: "5555550000" }
+				}
+			))
 		end
 
 		def test_poll
+			req = stub_request(
+				:post,
+				"https://api.catapult.inetwork.com/v1/users/catapult_user/phoneNumbers"
+			).with(
+				body: open(__dir__ + "/data/catapult_import_body.json").read.chomp,
+				headers: {
+					"Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0",
+					"Content-Type" => "application/json"
+				}
+			).to_return(status: 200)
 			assert_equal @order, @order.poll.sync
+			assert_requested req
 		end
 		em :test_poll
 	end

test/test_helper.rb 🔗

@@ -44,6 +44,12 @@ CONFIG = {
 		username: "test_bw_user",
 		password: "test_bw_password"
 	},
+	catapult: {
+		user: "catapult_user",
+		token: "catapult_token",
+		secret: "catapult_secret",
+		application_id: "catapult_app"
+	},
 	activation_amount: 1,
 	plans: [
 		{

test/test_registration.rb 🔗

@@ -365,8 +365,23 @@ class RegistrationTest < Minitest::Test
 			).to_return(status: 201, body: <<~RESPONSE)
 				<OrderResponse>
 					<OrderStatus>COMPLETE</OrderStatus>
+					<CompletedNumbers>
+						<TelephoneNumber>
+							<FullNumber>5555550000</FullNumber>
+						</TelephoneNumber>
+					</CompletedNumbers>
 				</OrderResponse>
 			RESPONSE
+			stub_request(
+				:post,
+				"https://api.catapult.inetwork.com/v1/users/catapult_user/phoneNumbers"
+			).with(
+				body: open(__dir__ + "/data/catapult_import_body.json").read.chomp,
+				headers: {
+					"Authorization" => "Basic Y2F0YXB1bHRfdG9rZW46Y2F0YXB1bHRfc2VjcmV0",
+					"Content-Type" => "application/json"
+				}
+			).to_return(status: 200)
 			BACKEND_SGX.expect(
 				:register!,
 				EMPromise.resolve(OpenStruct.new(error?: false)),