test_registration.rb

  1# frozen_string_literal: true
  2
  3require "test_helper"
  4require "customer"
  5require "registration"
  6
  7class RegistrationTest < Minitest::Test
  8	def test_for_registered
  9		sgx = OpenStruct.new(
 10			registered?: OpenStruct.new(phone: "+15555550000")
 11		)
 12		iq = Blather::Stanza::Iq::Command.new
 13		iq.from = "test@example.com"
 14		result = execute_command(iq) do
 15			Registration.for(
 16				customer(sgx: sgx),
 17				Minitest::Mock.new
 18			)
 19		end
 20		assert_kind_of Registration::Registered, result
 21	end
 22	em :test_for_registered
 23
 24	def test_for_activated
 25		web_manager = TelSelections.new(redis: FakeRedis.new)
 26		web_manager.set("test@example.net", "+15555550000")
 27		result = execute_command do
 28			sgx = OpenStruct.new(registered?: false)
 29			Registration.for(
 30				customer(
 31					plan_name: "test_usd",
 32					expires_at: Time.now + 999,
 33					sgx: sgx
 34				),
 35				web_manager
 36			)
 37		end
 38		assert_kind_of Registration::Finish, result
 39	end
 40	em :test_for_activated
 41
 42	def test_for_not_activated_approved
 43		sgx = OpenStruct.new(registered?: false)
 44		web_manager = TelSelections.new(redis: FakeRedis.new)
 45		web_manager.set("test\\40approved.example.com@component", "+15555550000")
 46		iq = Blather::Stanza::Iq::Command.new
 47		iq.from = "test@approved.example.com"
 48		result = execute_command(iq) do
 49			Registration::Activation.for(
 50				customer(
 51					sgx: sgx,
 52					jid: Blather::JID.new("test\\40approved.example.com@component")
 53				),
 54				web_manager
 55			)
 56		end
 57		assert_kind_of Registration::Activation::Allow, result
 58	end
 59	em :test_for_not_activated_approved
 60
 61	def test_for_not_activated_with_customer_id
 62		sgx = OpenStruct.new(registered?: false)
 63		web_manager = TelSelections.new(redis: FakeRedis.new)
 64		web_manager.set("test@example.net", "+15555550000")
 65		iq = Blather::Stanza::Iq::Command.new
 66		iq.from = "test@example.com"
 67		result = execute_command(iq) do
 68			Registration::Activation.for(
 69				customer(sgx: sgx),
 70				web_manager
 71			)
 72		end
 73		assert_kind_of Registration::Activation, result
 74	end
 75	em :test_for_not_activated_with_customer_id
 76
 77	class ActivationTest < Minitest::Test
 78		Command::COMMAND_MANAGER = Minitest::Mock.new
 79		def setup
 80			@activation = Registration::Activation.new("test", "+15555550000")
 81		end
 82
 83		def test_write
 84			stub_request(
 85				:get,
 86				"https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
 87			).to_return(status: 201, body: <<~RESPONSE)
 88				<TelephoneNumberResponse>
 89					<TelephoneNumber>5555550000</TelephoneNumber>
 90				</TelephoneNumberResponse>
 91			RESPONSE
 92			stub_request(
 93				:get,
 94				"https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
 95			).to_return(status: 201, body: <<~RESPONSE)
 96				<TelephoneNumberResponse>
 97					<TelephoneNumberDetails>
 98						<State>KE</State>
 99						<RateCenter>FA</RateCenter>
100					</TelephoneNumberDetails>
101				</TelephoneNumberResponse>
102			RESPONSE
103			Command::COMMAND_MANAGER.expect(
104				:write,
105				EMPromise.reject(:test_result),
106				[Matching.new do |iq|
107					assert_equal :form, iq.form.type
108					assert_equal(
109						"You've selected +15555550000 (FA, KE) as your JMP number.",
110						iq.form.instructions.lines.first.chomp
111					)
112				end]
113			)
114			assert_equal(
115				:test_result,
116				execute_command { @activation.write.catch { |e| e } }
117			)
118			assert_mock Command::COMMAND_MANAGER
119		end
120		em :test_write
121	end
122
123	class AllowTest < Minitest::Test
124		Command::COMMAND_MANAGER = Minitest::Mock.new
125		Registration::Activation::Allow::DB = Minitest::Mock.new
126
127		def test_write_credit_to_nil
128			cust = Minitest::Mock.new(customer("test"))
129			allow = Registration::Activation::Allow.new(cust, "+15555550000", nil)
130
131			stub_request(
132				:get,
133				"https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
134			).to_return(status: 201, body: <<~RESPONSE)
135				<TelephoneNumberResponse>
136					<TelephoneNumber>5555550000</TelephoneNumber>
137				</TelephoneNumberResponse>
138			RESPONSE
139			stub_request(
140				:get,
141				"https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
142			).to_return(status: 201, body: <<~RESPONSE)
143				<TelephoneNumberResponse>
144					<TelephoneNumberDetails>
145						<State>KE</State>
146						<RateCenter>FA</RateCenter>
147					</TelephoneNumberDetails>
148				</TelephoneNumberResponse>
149			RESPONSE
150			Command::COMMAND_MANAGER.expect(
151				:write,
152				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
153					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
154				}),
155				[Matching.new do |iq|
156					assert_equal :form, iq.form.type
157					assert_equal(
158						"You've selected +15555550000 (FA, KE) as your JMP number.",
159						iq.form.instructions.lines.first.chomp
160					)
161					assert_equal 1, iq.form.fields.length
162				end]
163			)
164			Registration::Activation::Allow::DB.expect(
165				:transaction,
166				EMPromise.reject(:test_result)
167			) do |&blk|
168				blk.call
169				true
170			end
171			cust.expect(:with_plan, cust, ["test_usd"])
172			cust.expect(:activate_plan_starting_now, nil)
173			assert_equal(
174				:test_result,
175				execute_command { allow.write.catch { |e| e } }
176			)
177			assert_mock Command::COMMAND_MANAGER
178		end
179		em :test_write_credit_to_nil
180
181		def test_write_credit_to_refercust
182			cust = Minitest::Mock.new(customer("test"))
183			allow = Registration::Activation::Allow.new(
184				cust, "+15555550000", "refercust"
185			)
186
187			stub_request(
188				:get,
189				"https://dashboard.bandwidth.com/v1.0/tns/+15555550000"
190			).to_return(status: 201, body: <<~RESPONSE)
191				<TelephoneNumberResponse>
192					<TelephoneNumber>5555550000</TelephoneNumber>
193				</TelephoneNumberResponse>
194			RESPONSE
195			stub_request(
196				:get,
197				"https://dashboard.bandwidth.com/v1.0/tns/5555550000/ratecenter"
198			).to_return(status: 201, body: <<~RESPONSE)
199				<TelephoneNumberResponse>
200					<TelephoneNumberDetails>
201						<State>KE</State>
202						<RateCenter>FA</RateCenter>
203					</TelephoneNumberDetails>
204				</TelephoneNumberResponse>
205			RESPONSE
206			Command::COMMAND_MANAGER.expect(
207				:write,
208				EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
209					iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
210				}),
211				[Matching.new do |iq|
212					assert_equal :form, iq.form.type
213					assert_equal(
214						"You've selected +15555550000 (FA, KE) as your JMP number.",
215						iq.form.instructions.lines.first.chomp
216					)
217					assert_equal 1, iq.form.fields.length
218				end]
219			)
220			Registration::Activation::Allow::DB.expect(
221				:transaction,
222				EMPromise.reject(:test_result)
223			) do |&blk|
224				blk.call
225				true
226			end
227			Registration::Activation::Allow::DB.expect(
228				:exec,
229				nil,
230				[String, ["refercust", "test"]]
231			)
232			cust.expect(:with_plan, cust, ["test_usd"])
233			cust.expect(:activate_plan_starting_now, nil)
234			assert_equal(
235				:test_result,
236				execute_command { allow.write.catch { |e| e } }
237			)
238			assert_mock Command::COMMAND_MANAGER
239		end
240		em :test_write_credit_to_refercust
241	end
242
243	class PaymentTest < Minitest::Test
244		CustomerFinancials::BRAINTREE = Minitest::Mock.new
245
246		def test_for_bitcoin
247			cust = Minitest::Mock.new(customer)
248			cust.expect(:with_plan, cust, ["test_usd"])
249			cust.expect(:save_plan!, nil)
250			iq = Blather::Stanza::Iq::Command.new
251			iq.form.fields = [
252				{ var: "activation_method", value: "bitcoin" },
253				{ var: "plan_name", value: "test_usd" }
254			]
255			result = Registration::Payment.for(iq, cust, "+15555550000")
256			assert_kind_of Registration::Payment::Bitcoin, result
257			assert_mock cust
258		end
259
260		def test_for_credit_card
261			cust = Minitest::Mock.new(customer)
262			cust.expect(:with_plan, cust, ["test_usd"])
263			cust.expect(:save_plan!, nil)
264			braintree_customer = Minitest::Mock.new
265			CustomerFinancials::BRAINTREE.expect(
266				:customer,
267				braintree_customer
268			)
269			CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"])
270			braintree_customer.expect(
271				:find,
272				EMPromise.resolve(OpenStruct.new(payment_methods: [])),
273				["test"]
274			)
275			iq = Blather::Stanza::Iq::Command.new
276			iq.from = "test@example.com"
277			iq.form.fields = [
278				{ var: "activation_method", value: "credit_card" },
279				{ var: "plan_name", value: "test_usd" }
280			]
281			result = Registration::Payment.for(
282				iq,
283				cust,
284				"+15555550000"
285			).sync
286			assert_kind_of Registration::Payment::CreditCard, result
287			assert_mock cust
288		end
289		em :test_for_credit_card
290
291		def test_for_code
292			cust = Minitest::Mock.new(customer)
293			cust.expect(:with_plan, cust, ["test_usd"])
294			cust.expect(:save_plan!, nil)
295			iq = Blather::Stanza::Iq::Command.new
296			iq.form.fields = [
297				{ var: "activation_method", value: "code" },
298				{ var: "plan_name", value: "test_usd" }
299			]
300			result = Registration::Payment.for(
301				iq,
302				cust,
303				"+15555550000"
304			)
305			assert_kind_of Registration::Payment::InviteCode, result
306			assert_mock cust
307		end
308
309		class BitcoinTest < Minitest::Test
310			Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
311			CustomerFinancials::REDIS = Minitest::Mock.new
312
313			def setup
314				@customer = Minitest::Mock.new(
315					customer(plan_name: "test_usd")
316				)
317				@customer.expect(
318					:add_btc_address,
319					EMPromise.resolve("testaddr")
320				)
321				@bitcoin = Registration::Payment::Bitcoin.new(
322					@customer,
323					"+15555550000"
324				)
325			end
326
327			def test_write
328				CustomerFinancials::REDIS.expect(
329					:smembers,
330					EMPromise.resolve([]),
331					["jmp_customer_btc_addresses-test"]
332				)
333				reply_text = <<~NOTE
334					Activate your account by sending at least 1.000000 BTC to
335					testaddr
336
337					You will receive a notification when your payment is complete.
338				NOTE
339				blather = Minitest::Mock.new
340				blather.expect(
341					:<<,
342					nil,
343					[Matching.new do |reply|
344						assert_equal :canceled, reply.status
345						assert_equal :info, reply.note_type
346						assert_equal reply_text, reply.note.content
347						true
348					end]
349				)
350				Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
351					:usd,
352					EMPromise.resolve(BigDecimal(1))
353				)
354				@bitcoin.stub(:save, EMPromise.resolve(nil)) do
355					execute_command(blather: blather) do
356						@bitcoin.write
357					end
358				end
359				assert_mock blather
360			end
361			em :test_write
362		end
363
364		class CreditCardTest < Minitest::Test
365			def setup
366				@credit_card = Registration::Payment::CreditCard.new(
367					customer,
368					"+15555550000"
369				)
370			end
371
372			def test_for
373				customer = Minitest::Mock.new(customer)
374				customer.expect(
375					:payment_methods,
376					EMPromise.resolve(OpenStruct.new(default_payment_method: :test))
377				)
378				assert_kind_of(
379					Registration::Payment::CreditCard::Activate,
380					Registration::Payment::CreditCard.for(
381						customer,
382						"+15555550000"
383					).sync
384				)
385			end
386			em :test_for
387
388			def test_write
389				result = execute_command do
390					Command::COMMAND_MANAGER.expect(
391						:write,
392						EMPromise.reject(:test_result),
393						[Matching.new do |reply|
394							assert_equal [:execute, :next], reply.allowed_actions
395							assert_equal(
396								"Add credit card, then return here to continue: " \
397								"http://creditcard.example.com",
398								reply.note.content
399							)
400						end]
401					)
402
403					@credit_card.write.catch { |e| e }
404				end
405
406				assert_equal :test_result, result
407			end
408			em :test_write
409		end
410
411		class ActivateTest < Minitest::Test
412			Registration::Payment::CreditCard::Activate::Finish =
413				Minitest::Mock.new
414			Registration::Payment::CreditCard::Activate::Transaction =
415				Minitest::Mock.new
416			Command::COMMAND_MANAGER = Minitest::Mock.new
417
418			def test_write
419				transaction = PromiseMock.new
420				transaction.expect(
421					:insert,
422					EMPromise.resolve(nil)
423				)
424				customer = Minitest::Mock.new(
425					customer(plan_name: "test_usd")
426				)
427				Registration::Payment::CreditCard::Activate::Transaction.expect(
428					:sale,
429					transaction
430				) do |acustomer, amount:, payment_method:|
431					assert_operator customer, :===, acustomer
432					assert_equal CONFIG[:activation_amount], amount
433					assert_equal :test_default_method, payment_method
434				end
435				customer.expect(:bill_plan, nil, [{ note: "Bill for first month" }])
436				Registration::Payment::CreditCard::Activate::Finish.expect(
437					:new,
438					OpenStruct.new(write: nil),
439					[customer, "+15555550000"]
440				)
441				execute_command do
442					Registration::Payment::CreditCard::Activate.new(
443						customer,
444						:test_default_method,
445						"+15555550000"
446					).write
447				end
448				Registration::Payment::CreditCard::Activate::Transaction.verify
449				transaction.verify
450				customer.verify
451				Registration::Payment::CreditCard::Activate::Finish.verify
452			end
453			em :test_write
454
455			def test_write_declines
456				customer = Minitest::Mock.new(
457					customer(plan_name: "test_usd")
458				)
459				iq = Blather::Stanza::Iq::Command.new
460				iq.from = "test@example.com"
461				msg = Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE
462				Command::COMMAND_MANAGER.expect(
463					:write,
464					EMPromise.reject(:test_result),
465					[Matching.new do |reply|
466						assert_equal :error, reply.note_type
467						assert_equal(
468							"#{msg}: http://creditcard.example.com",
469							reply.note.content
470						)
471					end]
472				)
473				result = execute_command do
474					Registration::Payment::CreditCard::Activate::Transaction.expect(
475						:sale,
476						EMPromise.reject("declined")
477					) do |acustomer, amount:, payment_method:|
478						assert_operator customer, :===, acustomer
479						assert_equal CONFIG[:activation_amount], amount
480						assert_equal :test_default_method, payment_method
481					end
482
483					Registration::Payment::CreditCard::Activate.new(
484						customer,
485						:test_default_method,
486						"+15555550000"
487					).write.catch { |e| e }
488				end
489				assert_equal :test_result, result
490				Registration::Payment::CreditCard::Activate::Transaction.verify
491			end
492			em :test_write_declines
493		end
494
495		class InviteCodeTest < Minitest::Test
496			Registration::Payment::InviteCode::DB =
497				Minitest::Mock.new
498			Registration::Payment::InviteCode::REDIS =
499				Minitest::Mock.new
500			Command::COMMAND_MANAGER = Minitest::Mock.new
501			Registration::Payment::InviteCode::Finish =
502				Minitest::Mock.new
503			def test_write
504				customer = customer(plan_name: "test_usd")
505				Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
506				Registration::Payment::InviteCode::Finish.expect(
507					:new,
508					OpenStruct.new(write: nil),
509					[
510						customer,
511						"+15555550000"
512					]
513				)
514				execute_command do
515					Registration::Payment::InviteCode::REDIS.expect(
516						:get,
517						EMPromise.resolve(nil),
518						["jmp_invite_tries-test"]
519					)
520					Command::COMMAND_MANAGER.expect(
521						:write,
522						EMPromise.resolve(
523							Blather::Stanza::Iq::Command.new.tap { |iq|
524								iq.form.fields = [{ var: "code", value: "abc" }]
525							}
526						),
527						[Matching.new do |reply|
528							assert_equal :form, reply.form.type
529							assert_nil reply.form.instructions
530						end]
531					)
532
533					Registration::Payment::InviteCode.new(
534						customer,
535						"+15555550000"
536					).write
537				end
538				assert_mock Command::COMMAND_MANAGER
539				assert_mock Registration::Payment::InviteCode::DB
540				assert_mock Registration::Payment::InviteCode::REDIS
541				assert_mock Registration::Payment::InviteCode::Finish
542			end
543			em :test_write
544
545			def test_write_bad_code
546				result = execute_command do
547					customer = customer(plan_name: "test_usd")
548					Registration::Payment::InviteCode::REDIS.expect(
549						:get,
550						EMPromise.resolve(0),
551						["jmp_invite_tries-test"]
552					)
553					Registration::Payment::InviteCode::DB.expect(:transaction, []) do
554						raise InvitesRepo::Invalid, "wut"
555					end
556					Registration::Payment::InviteCode::REDIS.expect(
557						:incr,
558						EMPromise.resolve(nil),
559						["jmp_invite_tries-test"]
560					)
561					Registration::Payment::InviteCode::REDIS.expect(
562						:expire,
563						EMPromise.resolve(nil),
564						["jmp_invite_tries-test", 60 * 60]
565					)
566					Command::COMMAND_MANAGER.expect(
567						:write,
568						EMPromise.resolve(
569							Blather::Stanza::Iq::Command.new.tap { |iq|
570								iq.form.fields = [{ var: "code", value: "abc" }]
571							}
572						),
573						[Matching.new do |reply|
574							assert_equal :form, reply.form.type
575							assert_nil reply.form.instructions
576						end]
577					)
578					Command::COMMAND_MANAGER.expect(
579						:write,
580						EMPromise.reject(:test_result),
581						[Matching.new do |reply|
582							assert_equal :form, reply.form.type
583							assert_equal "wut", reply.form.instructions
584						end]
585					)
586
587					Registration::Payment::InviteCode.new(
588						customer,
589						"+15555550000"
590					).write.catch { |e| e }
591				end
592				assert_equal :test_result, result
593				assert_mock Command::COMMAND_MANAGER
594				assert_mock Registration::Payment::InviteCode::DB
595				assert_mock Registration::Payment::InviteCode::REDIS
596			end
597			em :test_write_bad_code
598
599			def test_write_bad_code_over_limit
600				result = execute_command do
601					customer = customer(plan_name: "test_usd")
602					Registration::Payment::InviteCode::REDIS.expect(
603						:get,
604						EMPromise.resolve(11),
605						["jmp_invite_tries-test"]
606					)
607					Command::COMMAND_MANAGER.expect(
608						:write,
609						EMPromise.resolve(
610							Blather::Stanza::Iq::Command.new.tap { |iq|
611								iq.form.fields = [{ var: "code", value: "abc" }]
612							}
613						),
614						[Matching.new do |reply|
615							assert_equal :form, reply.form.type
616							assert_nil reply.form.instructions
617						end]
618					)
619					Registration::Payment::InviteCode::REDIS.expect(
620						:incr,
621						EMPromise.resolve(nil),
622						["jmp_invite_tries-test"]
623					)
624					Registration::Payment::InviteCode::REDIS.expect(
625						:expire,
626						EMPromise.resolve(nil),
627						["jmp_invite_tries-test", 60 * 60]
628					)
629					Command::COMMAND_MANAGER.expect(
630						:write,
631						EMPromise.reject(:test_result),
632						[Matching.new do |reply|
633							assert_equal :form, reply.form.type
634							assert_equal "Too many wrong attempts", reply.form.instructions
635						end]
636					)
637					Registration::Payment::InviteCode.new(
638						customer,
639						"+15555550000"
640					).write.catch { |e| e }
641				end
642				assert_equal :test_result, result
643				assert_mock Command::COMMAND_MANAGER
644				assert_mock Registration::Payment::InviteCode::REDIS
645			end
646			em :test_write_bad_code_over_limit
647		end
648	end
649
650	class FinishTest < Minitest::Test
651		Command::COMMAND_MANAGER = Minitest::Mock.new
652		Registration::Finish::TEL_SELECTIONS = FakeTelSelections.new
653		Registration::Finish::REDIS = Minitest::Mock.new
654		Bwmsgsv2Repo::REDIS = Minitest::Mock.new
655
656		def setup
657			@sgx = Minitest::Mock.new(TrivialBackendSgxRepo.new.get("test"))
658			iq = Blather::Stanza::Iq::Command.new
659			iq.from = "test\\40example.com@cheogram.com"
660			@finish = Registration::Finish.new(
661				customer(sgx: @sgx),
662				"+15555550000"
663			)
664		end
665
666		def test_write
667			create_order = stub_request(
668				:post,
669				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
670			).to_return(status: 201, body: <<~RESPONSE)
671				<OrderResponse>
672					<Order>
673						<id>test_order</id>
674					</Order>
675				</OrderResponse>
676			RESPONSE
677			stub_request(
678				:get,
679				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
680			).to_return(status: 201, body: <<~RESPONSE)
681				<OrderResponse>
682					<OrderStatus>COMPLETE</OrderStatus>
683					<CompletedNumbers>
684						<TelephoneNumber>
685							<FullNumber>5555550000</FullNumber>
686						</TelephoneNumber>
687					</CompletedNumbers>
688				</OrderResponse>
689			RESPONSE
690			stub_request(
691				:post,
692				"https://dashboard.bandwidth.com/v1.0/accounts//sites//sippeers//movetns"
693			)
694			Registration::Finish::REDIS.expect(
695				:del,
696				nil,
697				["pending_tel_for-test@example.net"]
698			)
699			Bwmsgsv2Repo::REDIS.expect(
700				:set,
701				nil,
702				[
703					"catapult_fwd-+15555550000",
704					"xmpp:test@example.net"
705				]
706			)
707			Bwmsgsv2Repo::REDIS.expect(
708				:set,
709				nil,
710				["catapult_fwd_timeout-customer_test@component", 25]
711			)
712			blather = Minitest::Mock.new
713			blather.expect(
714				:<<,
715				nil,
716				[Matching.new do |reply|
717					assert_equal :completed, reply.status
718					assert_equal :info, reply.note_type
719					assert_equal(
720						"Your JMP account has been activated as +15555550000",
721						reply.note.content
722					)
723				end]
724			)
725			execute_command(blather: blather) do
726				@sgx.expect(
727					:register!,
728					EMPromise.resolve(@sgx.with(
729						registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
730							ibr.phone = "+15555550000"
731						end
732					)),
733					["+15555550000"]
734				)
735
736				@finish.write
737			end
738			assert_requested create_order
739			assert_mock @sgx
740			assert_mock Registration::Finish::REDIS
741			assert_mock Bwmsgsv2Repo::REDIS
742			assert_mock blather
743		end
744		em :test_write
745
746		def test_write_tn_fail
747			create_order = stub_request(
748				:post,
749				"https://dashboard.bandwidth.com/v1.0/accounts//orders"
750			).to_return(status: 201, body: <<~RESPONSE)
751				<OrderResponse>
752					<Order>
753						<id>test_order</id>
754					</Order>
755				</OrderResponse>
756			RESPONSE
757			stub_request(
758				:get,
759				"https://dashboard.bandwidth.com/v1.0/accounts//orders/test_order"
760			).to_return(status: 201, body: <<~RESPONSE)
761				<OrderResponse>
762					<OrderStatus>FAILED</OrderStatus>
763				</OrderResponse>
764			RESPONSE
765
766			result = execute_command do
767				Command::COMMAND_MANAGER.expect(
768					:write,
769					EMPromise.reject(:test_result),
770					[Matching.new do |iq|
771						assert_equal :form, iq.form.type
772						assert_equal(
773							"The JMP number +15555550000 is no longer available.",
774							iq.form.instructions
775						)
776					end]
777				)
778
779				@finish.write.catch { |e| e }
780			end
781
782			assert_equal :test_result, result
783			assert_mock Command::COMMAND_MANAGER
784			assert_instance_of(
785				TelSelections::ChooseTel,
786				Registration::Finish::TEL_SELECTIONS["test@example.com"]
787			)
788			assert_requested create_order
789		end
790		em :test_write_tn_fail
791	end
792end