Initial tests for web routes

Stephen Paul Weber created

Change summary

Gemfile             |   1 
test/test_helper.rb |  12 ++++
test/test_web.rb    | 123 +++++++++++++++++++++++++++++++++++++++++++++++
web.rb              |   2 
4 files changed, 136 insertions(+), 2 deletions(-)

Detailed changes

Gemfile 🔗

@@ -35,6 +35,7 @@ end
 
 group(:test) do
 	gem "minitest"
+	gem "rack-test"
 	gem "rake"
 	gem "rantly"
 	gem "rubocop", "= 0.89.1"

test/test_helper.rb 🔗

@@ -196,7 +196,7 @@ class FakeRedis
 end
 
 class FakeDB
-	def initialize(items)
+	def initialize(items={})
 		@items = items
 	end
 
@@ -205,6 +205,16 @@ class FakeDB
 	end
 end
 
+class FakeIBRRepo
+	def initialize(registrations={})
+		@registrations = registrations
+	end
+
+	def registered?(jid, from:)
+		@registrations.dig(jid.to_s, from.to_s) || false
+	end
+end
+
 module EventMachine
 	class << self
 		# Patch EM.add_timer to be instant in tests

test/test_web.rb 🔗

@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require "rack/test"
+require "test_helper"
+require_relative "../web"
+
+Customer::BLATHER = Minitest::Mock.new
+
+class WebTest < Minitest::Test
+	include Rack::Test::Methods
+
+	def app
+		Web.opts[:customer_repo] = CustomerRepo.new(
+			redis: FakeRedis.new(
+				"jmp_customer_jid-customerid" => "customer@example.com",
+				"catapult_jid-+15551234567" => "customer_customerid@component"
+			),
+			db: FakeDB.new,
+			sgx_repo: Bwmsgsv2Repo.new(
+				redis: FakeRedis.new,
+				ibr_repo: FakeIBRRepo.new(
+					"sgx" => {
+						"customer_customerid@component" => IBR.new.tap do |ibr|
+							ibr.phone = "+15551234567"
+						end
+					}
+				)
+			)
+		)
+		Web.app
+	end
+
+	def test_outbound_forwards
+		post(
+			"/outbound/calls",
+			{ from: "customerid", to: "+15557654321" }.to_json,
+			{ "CONTENT_TYPE" => "application/json" }
+		)
+
+		assert last_response.ok?
+		assert_equal(
+			"<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response>" \
+			"<Forward from=\"+15551234567\" to=\"+15557654321\" />" \
+			"</Response>",
+			last_response.body
+		)
+	end
+	em :test_outbound_forwards
+
+	def test_voicemail
+		Customer::BLATHER.expect(
+			:<<,
+			nil,
+			[Matching.new do |stanza|
+				assert_equal "+15557654321@component", stanza.from.to_s
+				assert_equal "customer@example.com", stanza.to.to_s
+				assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
+			end]
+		)
+
+		post(
+			"/inbound/calls/CALLID/voicemail/audio",
+			{
+				"startTime" => "2021-01-01T00:00:00Z",
+				"endTime" => "2021-01-01T00:00:06Z",
+				"mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
+				"to" => "+15551234567",
+				"from" => "+15557654321"
+			}.to_json,
+			{ "CONTENT_TYPE" => "application/json" }
+		)
+
+		assert last_response.ok?
+		assert_mock Customer::BLATHER
+	end
+	em :test_voicemail
+
+	def test_anonymous_voicemail
+		Customer::BLATHER.expect(
+			:<<,
+			nil,
+			[Matching.new do |stanza|
+				assert_equal(
+					"16;phone-context=anonymous.phone-context.soprani.ca@component",
+					stanza.from.to_s
+				)
+				assert_equal "customer@example.com", stanza.to.to_s
+				assert_equal "https://jmp.chat/media", OOB.find_or_create(stanza).url
+			end]
+		)
+
+		post(
+			"/inbound/calls/CALLID/voicemail/audio",
+			{
+				"startTime" => "2021-01-01T00:00:00Z",
+				"endTime" => "2021-01-01T00:00:06Z",
+				"mediaUrl" => "https://voice.bandwidth.com/api/v2/accounts/1/media",
+				"to" => "+15551234567",
+				"from" => "Anonymous"
+			}.to_json,
+			{ "CONTENT_TYPE" => "application/json" }
+		)
+
+		assert last_response.ok?
+		assert_mock Customer::BLATHER
+	end
+	em :test_anonymous_voicemail
+
+	def test_voicemail_short
+		post(
+			"/inbound/calls/CALLID/voicemail/audio",
+			{
+				"startTime" => "2021-01-01T00:00:00Z",
+				"endTime" => "2021-01-01T00:00:05Z"
+			}.to_json,
+			{ "CONTENT_TYPE" => "application/json" }
+		)
+
+		assert last_response.ok?
+		assert_mock Customer::BLATHER
+	end
+	em :test_voicemail_short
+end

web.rb 🔗

@@ -46,7 +46,7 @@ end
 
 # rubocop:disable Metrics/ClassLength
 class Web < Roda
-	use Rack::Fiber # Must go first!
+	use Rack::Fiber unless ENV["ENV"] == "test" # Must go first!
 	use Sentry::Rack::CaptureExceptions
 	plugin :json_parser
 	plugin :public