1# frozen_string_literal: true
  2
  3require "test_helper"
  4
  5require "ostruct"
  6
  7require_relative "../lib/sim_order"
  8
  9class SIMOrderTest < Minitest::Test
 10	SIMOrder::DB = Minitest::Mock.new
 11	Transaction::DB = Minitest::Mock.new
 12
 13	def setup
 14		@price = 5000
 15		@plan_name = "better than no plan"
 16		@sim_repo = Minitest::Mock.new
 17		@sim = SIM.new(
 18			iccid: "123",
 19			nickname: nil,
 20			lpa_code: "LPA:abc",
 21			remaining_usage_kb: 1025,
 22			remaining_days: 3,
 23			notes: "no notes"
 24		)
 25	end
 26
 27	def test_for_enough_balance
 28		assert_kind_of(
 29			SIMOrder,
 30			SIMOrder.for(customer(balance: 60), price: @price, plan: @plan_name)
 31		)
 32	end
 33
 34	def test_for_insufficient_balance_with_top_up
 35		customer = customer(balance: 40)
 36
 37		LowBalance::AutoTopUp.stub(
 38			:for,
 39			OpenStruct.new(can_top_up?: true),
 40			[customer, @price]
 41		) do
 42			assert_kind_of(
 43				SIMOrder::WithTopUp,
 44				SIMOrder.for(customer, price: @price, plan: @plan_name)
 45			)
 46		end
 47	end
 48
 49	def test_for_insufficient_balance_please_top_up
 50		customer = customer(balance: 40)
 51
 52		LowBalance::AutoTopUp.stub(
 53			:for,
 54			OpenStruct.new(can_top_up?: false),
 55			[customer, @price]
 56		) do
 57			assert_kind_of(
 58				SIMOrder::PleaseTopUp,
 59				SIMOrder.for(customer, price: @price, plan: @plan_name)
 60			)
 61		end
 62	end
 63
 64	def test_complete_nil_nick
 65		customer = Minitest::Mock.new(customer("123", balance: 100))
 66		customer.expect(
 67			:stanza_from,
 68			EMPromise.resolve(nil),
 69			[Blather::Stanza::Message]
 70		)
 71
 72		SIMOrder::DB.expect(
 73			:transaction,
 74			EMPromise.resolve(@sim)
 75		) do |&blk|
 76			blk.call
 77		end
 78
 79		Transaction::DB.expect(
 80			:exec,
 81			nil,
 82			[
 83				String,
 84				Matching.new { |params|
 85					assert_equal "123", params[0]
 86					assert_equal "tx123", params[1]
 87					assert_kind_of Time, params[2]
 88					assert_kind_of Time, params[3]
 89					assert_in_delta(-(@price / 100).to_d, params[4], 0.05)
 90					assert_equal "SIM Activation 123", params[5]
 91				}
 92			]
 93		)
 94
 95		@sim_repo.expect(:available, EMPromise.resolve(@sim), [])
 96		@sim_repo.expect(:put_owner, nil, [@sim, customer, "SIM"])
 97		@sim_repo.expect(
 98			:refill,
 99			EMPromise.resolve(OpenStruct.new(ack: "success", transaction_id: "tx123"))
100		) do |refill_sim, amount_mb:|
101			@sim == refill_sim && amount_mb == 1024
102		end
103
104		order_form = Blather::Stanza::Iq::Command.new.tap { |iq|
105			iq.form.fields = [
106				{ var: "addr", value: "123 Main St" },
107				{ var: "nickname", value: nil }
108			]
109		}
110
111		blather = Minitest::Mock.new
112		blather.expect(
113			:<<,
114			EMPromise.resolve(:test_result),
115			[Matching.new do |reply|
116				assert_equal :completed, reply.status
117				assert_equal :info, reply.note_type
118				assert_equal(
119					"You will receive an notice from support when your SIM ships.",
120					reply.note.content
121				)
122			end]
123		)
124		sim_order = SIMOrder.for(customer, price: @price, plan: @plan_name)
125		sim_order.instance_variable_set(:@sim_repo, @sim_repo)
126
127		assert_equal(
128			:test_result,
129			execute_command(blather: blather) { sim_order.complete(order_form) }
130		)
131
132		assert_mock Transaction::DB
133		assert_mock SIMOrder::DB
134		assert_mock customer
135		assert_mock @sim_repo
136		assert_mock blather
137	end
138	em :test_complete_nil_nick
139
140	def test_complete_nick_present
141		customer = Minitest::Mock.new(customer("123", balance: 100))
142		customer.expect(
143			:stanza_from,
144			EMPromise.resolve(nil),
145			[Blather::Stanza::Message]
146		)
147		Transaction::DB.expect(
148			:exec,
149			nil,
150			[
151				String,
152				Matching.new { |params|
153					assert_equal "123", params[0]
154					assert_equal "tx123", params[1]
155					assert_kind_of Time, params[2]
156					assert_kind_of Time, params[3]
157					assert_in_delta(-(@price / 100).to_d, params[4], 0.05)
158					assert_equal "SIM Activation 123", params[5]
159				}
160			]
161		)
162
163		SIMOrder::DB.expect(
164			:transaction,
165			@sim
166		) do |&blk|
167			blk.call
168		end
169
170		@sim_repo.expect(:available, EMPromise.resolve(@sim), [])
171		@sim_repo.expect(
172			:put_owner,
173			nil,
174			[@sim, customer, "test_nick"]
175		)
176		@sim_repo.expect(
177			:refill,
178			EMPromise.resolve(OpenStruct.new(ack: "success", transaction_id: "tx123"))
179		) do |refill_sim, amount_mb:|
180			@sim == refill_sim && amount_mb == 1024
181		end
182
183		order_form = Blather::Stanza::Iq::Command.new.tap { |iq|
184			iq.form.fields = [
185				{ var: "addr", value: "123 Main St" },
186				{ var: "nickname", value: "test_nick" }
187			]
188		}
189
190		blather = Minitest::Mock.new
191		blather.expect(
192			:<<,
193			EMPromise.resolve(:test_result),
194			[Matching.new do |reply|
195				assert_equal :completed, reply.status
196				assert_equal :info, reply.note_type
197				assert_equal(
198					"You will receive an notice from support when your SIM ships.",
199					reply.note.content
200				)
201			end]
202		)
203		sim_order = SIMOrder.for(customer, price: @price, plan: @plan_name)
204		sim_order.instance_variable_set(:@sim_repo, @sim_repo)
205
206		assert_equal(
207			:test_result,
208			execute_command(blather: blather) { sim_order.complete(order_form) }
209  )
210
211		assert_mock Transaction::DB
212		assert_mock SIMOrder::DB
213		assert_mock customer
214		assert_mock @sim_repo
215		assert_mock blather
216	end
217	em :test_complete_nick_present
218end