Validate that amount of credit to buy is in valid range

Stephen Paul Weber created

Change summary

lib/buy_account_credit_form.rb       | 17 +++++++++++++++--
sgx_jmp.rb                           |  2 ++
test/test_buy_account_credit_form.rb | 19 +++++++++++++++----
3 files changed, 32 insertions(+), 6 deletions(-)

Detailed changes

lib/buy_account_credit_form.rb 🔗

@@ -3,6 +3,15 @@
 require_relative "./xep0122_field"
 
 class BuyAccountCreditForm
+	class AmountValidationError < StandardError
+		def initialize(amount)
+			super(
+				"amount #{amount} must be in the range " \
+				"#{RANGE.first} through #{RANGE.last}"
+			)
+		end
+	end
+
 	def self.for(customer)
 		customer.payment_methods.then do |payment_methods|
 			new(customer.balance, payment_methods)
@@ -14,10 +23,12 @@ class BuyAccountCreditForm
 		@payment_methods = payment_methods
 	end
 
+	RANGE = (15..1000)
+
 	AMOUNT_FIELD =
 		XEP0122Field.new(
 			"xs:decimal",
-			range: (0..1000),
+			range: RANGE,
 			var: "amount",
 			label: "Amount of credit to buy",
 			required: true
@@ -41,11 +52,13 @@ class BuyAccountCreditForm
 	end
 
 	def parse(form)
+		amount = form.field("amount")&.value&.to_s
+		raise AmountValidationError, amount unless RANGE.include?(amount.to_i)
 		{
 			payment_method: @payment_methods.fetch(
 				form.field("payment_method")&.value.to_i
 			),
-			amount: form.field("amount")&.value&.to_s
+			amount: amount
 		}
 	end
 end

sgx_jmp.rb 🔗

@@ -327,6 +327,8 @@ command :execute?, node: "buy credit", sessionid: nil do |iq|
 		transaction.insert.then { transaction.amount }
 	}.then { |amount|
 		reply_with_note(iq, "$#{'%.2f' % amount} added to your account balance.")
+	}.catch_only(BuyAccountCreditForm::AmountValidationError) { |e|
+		reply_with_note(iq, e.message, type: :error)
 	}.catch { |e|
 		sentry_hub.capture_exception(e)
 		text = "Failed to buy credit, system said: #{e.message}"

test/test_buy_account_credit_form.rb 🔗

@@ -10,7 +10,7 @@ class BuyAccountCreditFormTest < Minitest::Test
 	def setup
 		@payment_method = OpenStruct.new(card_type: "Test", last_4: "1234")
 		@form = BuyAccountCreditForm.new(
-			BigDecimal.new("12.1234"),
+			BigDecimal.new("15.1234"),
 			PaymentMethods.new([@payment_method])
 		)
 	end
@@ -31,7 +31,7 @@ class BuyAccountCreditFormTest < Minitest::Test
 
 	def test_balance
 		assert_equal(
-			{ type: "fixed", value: "Current balance: $12.12" },
+			{ type: "fixed", value: "Current balance: $15.12" },
 			@form.balance
 		)
 	end
@@ -45,7 +45,7 @@ class BuyAccountCreditFormTest < Minitest::Test
 			[
 				Blather::Stanza::X::Field.new(
 					type: "fixed",
-					value: "Current balance: $12.12"
+					value: "Current balance: $15.12"
 				),
 				Blather::Stanza::X::Field.new(
 					type: "list-single",
@@ -66,9 +66,20 @@ class BuyAccountCreditFormTest < Minitest::Test
 		assert_equal "123", @form.parse(iq_form)[:amount]
 	end
 
+	def test_parse_bad_amount
+		iq_form = Blather::Stanza::X.new
+		iq_form.fields = [{ var: "amount", value: "1" }]
+		assert_raises(BuyAccountCreditForm::AmountValidationError) do
+			@form.parse(iq_form)[:amount]
+		end
+	end
+
 	def test_parse_payment_method
 		iq_form = Blather::Stanza::X.new
-		iq_form.fields = [{ var: "payment_method", value: "0" }]
+		iq_form.fields = [
+			{ var: "payment_method", value: "0" },
+			{ var: "amount", value: "15" }
+		]
 		assert_equal @payment_method, @form.parse(iq_form)[:payment_method]
 	end
 end