1# frozen_string_literal: true
   2
   3require "test_helper"
   4require "admin_command"
   5require "admin_action"
   6
   7BackendSgx::IQ_MANAGER = Minitest::Mock.new
   8BackendSgx::REDIS = Minitest::Mock.new
   9AdminAction::LaunchSnikket::IQ_MANAGER = Minitest::Mock.new
  10Customer::BLATHER = Minitest::Mock.new
  11AdminActionRepo::REDIS = Minitest::Mock.new
  12TrivialBackendSgxRepo::REDIS = Minitest::Mock.new
  13BandwidthTnRepo::DB = Minitest::Mock.new
  14AdminAction::NumberChange::REDIS = Minitest::Mock.new
  15
  16class AdminCommandTest < Minitest::Test
  17	def assert_undoable_form(iq, note_type=nil, note_text=nil)
  18		assert_equal :form, iq.form.type
  19		[:execute, :next, :complete].each do |action|
  20			assert iq.allowed_actions.include?(action)
  21		end
  22		assert_equal iq.note_type, note_type if note_type
  23
  24		assert iq.note_text = note_text if note_text
  25	end
  26
  27	def assert_change_number_form(iq)
  28		assert_equal(
  29			iq.form.field("new_tel")&.type,
  30			"text-single"
  31		)
  32		assert_equal(
  33			iq.form.field("new_backend")&.type,
  34			"text-single"
  35		)
  36		assert_equal(
  37			iq.form.field("should_delete")&.type,
  38			"boolean"
  39		)
  40	end
  41
  42	def change_number_form(
  43		new_tel: nil,
  44		new_backend: nil,
  45		should_delete: false,
  46		from: "test@example.com"
  47	)
  48		iq = Blather::Stanza::Iq::Command.new
  49		iq.form.fields = [
  50			{ var: "new_tel", value: new_tel },
  51			{ var: "should_delete", value: should_delete.to_s },
  52			{ var: "new_backend", value: new_backend }
  53		]
  54		iq.from = from
  55		iq
  56	end
  57
  58	def setup_bandwidth_tn_repo_mock(
  59		should_disconnect: false,
  60		old_tel: nil,
  61		new_tel: nil
  62	)
  63		mock_repo = Minitest::Mock.new
  64		if should_disconnect
  65			expected_order_name = "cust test swap to #{new_tel}"
  66			mock_repo.expect(
  67				:disconnect,
  68				EMPromise.resolve(nil),
  69				[old_tel, expected_order_name]
  70			)
  71		end
  72		mock_repo
  73	end
  74
  75	def assert_ibr_register_form(
  76		iq,
  77		tel,
  78		nick: "test_bw_account",
  79		username: "test_bw_user",
  80		password: "test_bw_password",
  81		from: "customer_test@component",
  82		target_backend_sgx: "sgx"
  83	)
  84		assert iq.is_a?(Blather::Stanza::Iq::IBR)
  85		assert_equal iq.type, :set
  86		assert_equal iq.nick, nick
  87		assert_equal iq.username, username
  88		assert_equal iq.password, password
  89		assert_equal iq.phone, tel
  90		assert_equal iq.from, from
  91		assert_equal iq.to, target_backend_sgx
  92	end
  93
  94	def assert_ibr_deregister_form(
  95		iq,
  96		from: "customer_test@component",
  97		target_backend_sgx: "sgx"
  98	)
  99		assert iq.is_a?(Blather::Stanza::Iq::IBR)
 100		assert_equal iq.type, :set
 101		assert_equal iq.to, target_backend_sgx
 102		assert_equal iq.from, from
 103		assert iq.remove?
 104	end
 105
 106	def admin_command(tel="+15556667777", registered: OpenStruct.new(phone: tel))
 107		sgx = Minitest::Mock.new(OpenStruct.new(
 108			registered?: registered
 109		))
 110		[
 111			sgx,
 112			AdminCommand.new(
 113				customer(sgx: sgx),
 114				CustomerRepo.new(db: FakeDB.new),
 115				AdminActionRepo.new,
 116				Snikket::Repo.new(db: FakeDB.new)
 117			)
 118		]
 119	end
 120
 121	def test_no_user
 122		q_form = Blather::Stanza::Iq::Command.new
 123		q_form.action = :complete
 124		q_form.form.fields = [
 125			{ var: "q", value: "testuser" }
 126		]
 127
 128		customer_repo = Minitest::Mock.new
 129
 130		result = execute_command {
 131			customer_repo.expect(
 132				:find_by_format,
 133				EMPromise.resolve(OpenStruct.new(
 134					customer_id: "testuser",
 135					billing_customer_id: "testuser",
 136					balance: 0.to_d,
 137					jid: Blather::JID.new("test@example.com"),
 138					tndetails: {}
 139				)),
 140				["testuser"]
 141			)
 142
 143			customer_repo.expect(
 144				:find_by_format,
 145				EMPromise.resolve(nil),
 146				[Blather::JID]
 147			)
 148
 149			customer_repo.expect(
 150				:find_by_format,
 151				EMPromise.resolve(nil),
 152				[ProxiedJID]
 153			)
 154
 155			TrivialBackendSgxRepo::REDIS.expect(
 156				:get,
 157				EMPromise.resolve(nil),
 158				["jmp_customer_backend_sgx-testuser"]
 159			)
 160
 161			TrustLevelRepo::REDIS.expect(
 162				:get,
 163				EMPromise.resolve("Customer"),
 164				["jmp_customer_trust_level-testuser"]
 165			)
 166
 167			TrustLevelRepo::DB.expect(
 168				:query_one,
 169				EMPromise.resolve({ settled_amount: 0 }),
 170				[String, "testuser"], default: {}
 171			)
 172
 173			Subaccount::DB.expect(
 174				:query_defer,
 175				EMPromise.resolve([]),
 176				[String, ["testuser"]]
 177			)
 178
 179			Command::COMMAND_MANAGER.expect(
 180				:write,
 181				EMPromise.resolve(q_form),
 182				[Matching.new do |iq|
 183					assert_equal :form, iq.form.type
 184					assert iq.form.field("q")
 185				end]
 186			)
 187
 188			AdminCommand.for(nil, customer_repo).start.catch { |e| e }
 189		}
 190
 191		assert result.stanza.completed?
 192		assert_mock customer_repo
 193		assert_mock Command::COMMAND_MANAGER
 194		assert_mock TrustLevelRepo::REDIS
 195		assert_mock Subaccount::DB
 196		assert_mock TrivialBackendSgxRepo::REDIS
 197	end
 198	em :test_no_user
 199
 200	def test_action_launch_snikket
 201		sgx, admin = admin_command
 202		domain_form = Blather::Stanza::Iq::Command.new
 203		domain_form.form.fields = [
 204			{ var: "domain", value: "test.snikket.chat" }
 205		]
 206
 207		launched = Snikket::Launched.new
 208		launched << Niceogiri::XML::Node.new(
 209			:launched, launched.document, "xmpp:snikket.org/hosting/v1"
 210		).tap { |inner|
 211			inner << Niceogiri::XML::Node.new(
 212				:'instance-id', launched.document, "xmpp:snikket.org/hosting/v1"
 213			).tap { |id|
 214				id.content = "si-1234"
 215			}
 216			inner << Niceogiri::XML::Node.new(
 217				:bootstrap, launched.document, "xmpp:snikket.org/hosting/v1"
 218			).tap { |bootstrap|
 219				bootstrap << Niceogiri::XML::Node.new(
 220					:token, launched.document, "xmpp:snikket.org/hosting/v1"
 221				).tap { |token|
 222					token.content = "TOKEN"
 223				}
 224			}
 225		}
 226
 227		result = execute_command {
 228			Command::COMMAND_MANAGER.expect(
 229				:write,
 230				EMPromise.resolve(domain_form),
 231				[Matching.new do |iq|
 232					assert_equal :form, iq.form.type
 233					assert iq.form.field("domain")
 234				end]
 235			)
 236			Command::COMMAND_MANAGER.expect(
 237				:write,
 238				EMPromise.reject(:test_result),
 239				[Matching.new do |iq|
 240					assert :result, iq.type
 241					assert(
 242						"https://test.snikket.chat/invites_bootstrap?token=TOKEN",
 243						iq.form.field("bootstrap-uri").value
 244					)
 245				end]
 246			)
 247
 248			AdminAction::LaunchSnikket::IQ_MANAGER.expect(
 249				:write,
 250				EMPromise.resolve(launched),
 251				[Matching.new do |iq|
 252					assert_equal :set, iq.type
 253					assert_equal CONFIG[:snikket_hosting_api], iq.to.to_s
 254					assert_equal(
 255						"test.snikket.chat",
 256						iq.xpath(
 257							"./ns:launch/ns:domain",
 258							ns: "xmpp:snikket.org/hosting/v1"
 259						).text
 260					)
 261				end]
 262			)
 263
 264			admin.action_launch_snikket.catch { |e| e }
 265		}
 266
 267		assert_equal :test_result, result
 268		assert_mock sgx
 269		assert_mock AdminAction::LaunchSnikket::IQ_MANAGER
 270		assert_mock Customer::BLATHER
 271	end
 272	em :test_action_launch_snikket
 273
 274	def test_action_cancel_account
 275		req = stub_request(:post, "https://api.churnbuster.io/v1/cancellations")
 276			.with(
 277				body: {
 278					customer: {
 279						source: "braintree",
 280						source_id: "test",
 281						email: "test@smtp.cheogram.com",
 282						properties: {}
 283					},
 284					subscription: {
 285						source: "braintree",
 286						source_id: "test"
 287					}
 288				}.to_json
 289			)
 290			.to_return(status: 200, body: "", headers: {})
 291
 292		sgx, admin = admin_command
 293
 294		Customer::BLATHER.expect(
 295			:<<,
 296			EMPromise.resolve(nil),
 297			[
 298				Matching.new do |m|
 299					assert_equal "Your JMP account has been cancelled.", m.body
 300					assert_equal "test@example.net", m.to.to_s
 301					assert_equal "notify_from@component", m.from.to_s
 302				end
 303			]
 304		)
 305
 306		Customer::BLATHER.expect(
 307			:<<,
 308			EMPromise.resolve(nil),
 309			[
 310				Matching.new do |iq|
 311					assert iq.remove?
 312					assert_equal "test@example.net", iq.to.to_s
 313					assert_equal "component", iq.from.to_s
 314				end
 315			]
 316		)
 317
 318		sgx.expect(:deregister!, EMPromise.resolve(nil))
 319
 320		stub_request(
 321			:post,
 322			"https://dashboard.bandwidth.com/v1.0/accounts//disconnects"
 323		).with(
 324			body: {
 325				name: "test",
 326				DisconnectTelephoneNumberOrderType: {
 327					TelephoneNumberList: {
 328						TelephoneNumber: "5556667777"
 329					}
 330				}
 331			}.to_xml(indent: 0, root: "DisconnectTelephoneNumberOrder")
 332		).to_return(status: 200, body: "")
 333
 334		admin.action_cancel_account.sync
 335
 336		assert_mock sgx
 337		assert_mock BackendSgx::IQ_MANAGER
 338		assert_mock Customer::BLATHER
 339		assert_requested req
 340	end
 341	em :test_action_cancel_account
 342
 343	def test_action_cancel_account_keep_number
 344		details_response = {
 345			"TelephoneNumberDetails": {
 346				State: "NY",
 347				City: "MANHATTEN"
 348			}
 349		}.to_xml(indent: 0, root: "TelephoneNumberResponse")
 350
 351		bandwidth_req = stub_request(
 352			:get,
 353			"https://dashboard.bandwidth.com/v1.0/tns/5566667777/tndetails"
 354		).with(
 355			headers: {
 356				"Accept" => "application/xml",
 357				"Accept-Encoding" => "gzip, compressed",
 358				"Authorization" => "Basic dGVzdF9id191c2VyOnRlc3RfYndfcGFzc3dvcmQ=",
 359				"User-Agent" => "Ruby-Bandwidth-Iris"
 360			}
 361		).to_return(status: 200, body: details_response, headers: {})
 362
 363		churnbuster_req = stub_request(
 364			:post,
 365			"https://api.churnbuster.io/v1/cancellations"
 366		)
 367			.with(
 368				body: {
 369					customer: {
 370						source: "braintree",
 371						source_id: "test",
 372						email: "test@smtp.cheogram.com",
 373						properties: {}
 374					},
 375					subscription: {
 376						source: "braintree",
 377						source_id: "test"
 378					}
 379				}.to_json
 380			)
 381			.to_return(status: 200, body: "", headers: {})
 382
 383		sgx, admin = admin_command("+15566667777")
 384
 385		sql_params = ["+15566667777", "NY", "MANHATTEN", "test_bw_account"]
 386
 387		BandwidthTnRepo::DB.expect(
 388			:exec,
 389			EMPromise.resolve(nil),
 390			[String, sql_params]
 391		)
 392
 393		Customer::BLATHER.expect(
 394			:<<,
 395			EMPromise.resolve(nil),
 396			[
 397				Matching.new do |m|
 398					assert_equal "Your JMP account has been cancelled.", m.body
 399					assert_equal "test@example.net", m.to.to_s
 400					assert_equal "notify_from@component", m.from.to_s
 401				end
 402			]
 403		)
 404
 405		Customer::BLATHER.expect(
 406			:<<,
 407			EMPromise.resolve(nil),
 408			[
 409				Matching.new do |iq|
 410					assert iq.remove?
 411					assert_equal "test@example.net", iq.to.to_s
 412					assert_equal "component", iq.from.to_s
 413				end
 414			]
 415		)
 416
 417		sgx.expect(:deregister!, EMPromise.resolve(nil))
 418
 419		admin.action_cancel_account.sync
 420
 421		assert_mock sgx
 422		assert_mock BackendSgx::IQ_MANAGER
 423		assert_mock Customer::BLATHER
 424		assert_mock BandwidthTnRepo::DB
 425
 426		assert_requested churnbuster_req
 427		assert_requested bandwidth_req
 428	end
 429	em :test_action_cancel_account_keep_number
 430
 431	def test_change_num_for_unregistered_customer
 432		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 433			should_disconnect: false
 434		)
 435
 436		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 437			execute_command { |exe|
 438				sgx = Minitest::Mock.new(OpenStruct.new(
 439					registered?: false,
 440					jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 441				))
 442				target_customer = customer(sgx: sgx)
 443
 444				exe.customer_repo.expect(
 445					:find_by_jid,
 446					EMPromise.resolve(target_customer),
 447					[Matching.new do |jid|
 448						assert jid.is_a? Blather::JID
 449						assert_equal jid.stripped.to_s, "test@example.com"
 450					end]
 451				)
 452
 453				AdminAction::NumberChange::REDIS.expect(
 454					:get,
 455					EMPromise.resolve(nil),
 456					["jmp_customer_backend_sgx-test"]
 457				)
 458
 459				AdminAction::NumberChange::REDIS.expect(
 460					:get,
 461					EMPromise.resolve(nil),
 462					["jmp_customer_backend_sgx-test"]
 463				)
 464
 465				AdminAction::NumberChange::REDIS.expect(
 466					:del,
 467					EMPromise.resolve(nil),
 468					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 469				)
 470
 471				BackendSgx::IQ_MANAGER.expect(
 472					:write,
 473					EMPromise.resolve(nil)
 474				) do |iq|
 475					assert_ibr_deregister_form(iq)
 476				end
 477
 478				BackendSgx::IQ_MANAGER.expect(
 479					:write,
 480					EMPromise.resolve(nil)
 481				) do |iq|
 482					assert_ibr_register_form(
 483						iq,
 484						"+12222222222"
 485					)
 486				end
 487
 488				BackendSgx::REDIS.expect(
 489					:set,
 490					EMPromise.resolve(nil),
 491					["catapult_jid-+12222222222", "customer_test@component"]
 492				)
 493
 494				expected_xadd_args = {
 495					customer_id: "test",
 496					old_tel: nil,
 497					new_tel: "+12222222222",
 498					should_delete: nil,
 499					actor_id: "test",
 500					class: "NumberChange",
 501					direction: :forward
 502				}.freeze
 503
 504				AdminActionRepo::REDIS.expect(
 505					:xadd,
 506					EMPromise.resolve(nil)
 507				) do |admin_actions, star, **xadd_args|
 508					assert_equal admin_actions, "admin_actions"
 509					assert_equal star, "*"
 510
 511					xadd_args.each do |k, v|
 512						assert_equal v, expected_xadd_args[k]
 513					end
 514				end
 515
 516				Command::COMMAND_MANAGER.expect(
 517					:write,
 518					EMPromise.resolve(change_number_form(
 519						new_tel: "+12222222222"
 520					))
 521				) do |iq|
 522					assert_undoable_form(iq)
 523					assert_change_number_form(iq)
 524				end
 525
 526				result = AdminCommand.for(
 527					target_customer,
 528					exe.customer_repo
 529				).action_number_change.sync
 530
 531				slug, backend_report, number_report = result.lines
 532
 533				assert_equal slug.strip, "Action : Change Number"
 534				assert_equal(
 535					backend_report.strip,
 536					"[move backend?]: sgx -> sgx"
 537				)
 538				assert_equal(
 539					number_report.strip,
 540					"[change number?]: nil -> +12222222222"
 541				)
 542
 543				assert_mock Command::COMMAND_MANAGER
 544				assert_mock exe.customer_repo
 545				assert_mock AdminAction::NumberChange::REDIS
 546				assert_mock AdminActionRepo::REDIS
 547				assert_mock BackendSgx::REDIS
 548				assert_mock BackendSgx::IQ_MANAGER
 549				assert_mock bandwidth_tn_repo_mock
 550				assert_mock sgx
 551			}
 552		end
 553	end
 554	em :test_change_num_for_unregistered_customer
 555
 556	def test_change_num_for_unregistered_customer_blank_new_tel
 557		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 558			should_disconnect: false
 559		)
 560
 561		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 562			execute_command { |exe|
 563				sgx = Minitest::Mock.new(OpenStruct.new(
 564					registered?: false,
 565					jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 566				))
 567				target_customer = customer(sgx: sgx)
 568
 569				exe.customer_repo.expect(
 570					:find_by_jid,
 571					EMPromise.resolve(target_customer),
 572					[Matching.new do |jid|
 573						assert jid.is_a? Blather::JID
 574						assert_equal jid.stripped.to_s, "test@example.com"
 575					end]
 576				)
 577
 578				Command::COMMAND_MANAGER.expect(
 579					:write,
 580					EMPromise.resolve(change_number_form(
 581						new_tel: ""
 582					))
 583				) do |iq|
 584					assert_undoable_form(iq)
 585					assert_change_number_form(iq)
 586				end
 587
 588				result = assert_raises {
 589					AdminCommand.for(
 590						target_customer,
 591						exe.customer_repo
 592					).action_number_change.sync
 593				}
 594
 595				assert_kind_of AdminAction::NumberChange::Orphan, result
 596
 597				assert_mock Command::COMMAND_MANAGER
 598				assert_mock exe.customer_repo
 599				assert_mock bandwidth_tn_repo_mock
 600				assert_mock sgx
 601			}
 602		end
 603	end
 604	em :test_change_num_for_unregistered_customer_blank_new_tel
 605
 606	def test_change_num_same_num_same_backend
 607		# Same as default given by `sgx.registered?` returned by `admin_command`
 608		tel = "+15556667777"
 609
 610		execute_command { |exe|
 611			sgx = Minitest::Mock.new(OpenStruct.new(
 612				registered?: OpenStruct.new(phone: tel),
 613				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 614			))
 615
 616			target_customer = customer(sgx: sgx)
 617			admin = AdminCommand.for(target_customer, exe.customer_repo)
 618
 619			exe.customer_repo.expect(
 620				:find_by_jid,
 621				EMPromise.resolve(target_customer),
 622				[Matching.new do |jid|
 623					assert jid.is_a? Blather::JID
 624					assert_equal jid.stripped.to_s, "test@example.com"
 625				end]
 626			)
 627
 628			Command::COMMAND_MANAGER.expect(
 629				:write,
 630				EMPromise.resolve(change_number_form(
 631					new_tel: tel,
 632					new_backend: "sgx"
 633				)),
 634				[Matching.new do |iq|
 635					assert_undoable_form(iq)
 636					assert_change_number_form(iq)
 637				end]
 638			)
 639
 640			error = admin.action_number_change
 641				.catch_only(AdminAction::NoOp) { |e| e }.sync
 642
 643			assert error.is_a?(AdminAction::NoOp)
 644			assert_mock Command::COMMAND_MANAGER
 645			assert_mock exe.customer_repo
 646			assert_mock AdminAction::NumberChange::REDIS
 647			assert_mock sgx
 648		}
 649	end
 650	em :test_change_num_same_num_same_backend
 651
 652	def test_change_num_blank_num_blank_backend
 653		# Same as default given by `sgx.registered?` returned by `admin_command`
 654		tel = "+15556667777"
 655
 656		execute_command { |exe|
 657			sgx = Minitest::Mock.new(OpenStruct.new(
 658				registered?: OpenStruct.new(phone: tel),
 659				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 660			))
 661
 662			target_customer = customer(sgx: sgx)
 663
 664			admin = AdminCommand.for(target_customer, exe.customer_repo)
 665
 666			exe.customer_repo.expect(
 667				:find_by_jid,
 668				EMPromise.resolve(target_customer),
 669				[Matching.new do |jid|
 670					assert jid.is_a? Blather::JID
 671					assert_equal jid.stripped.to_s, "test@example.com"
 672				end]
 673			)
 674
 675			Command::COMMAND_MANAGER.expect(
 676				:write,
 677				EMPromise.resolve(change_number_form),
 678				[Matching.new do |iq|
 679					assert_undoable_form(iq)
 680					assert_change_number_form(iq)
 681				end]
 682			)
 683
 684			error = admin.action_number_change
 685				.catch_only(AdminAction::NoOp) { |e| e }.sync
 686
 687			assert error.is_a?(AdminAction::NoOp)
 688			assert_mock Command::COMMAND_MANAGER
 689			assert_mock exe.customer_repo
 690			assert_mock AdminAction::NumberChange::REDIS
 691			assert_mock sgx
 692		}
 693	end
 694	em :test_change_num_blank_num_blank_backend
 695
 696	def test_change_num_different_num_same_backend
 697		old_tel = "+15556667777"
 698		new_tel = "+12222222222"
 699		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 700			should_disconnect: false
 701		)
 702
 703		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 704			execute_command { |exe|
 705				sgx = Minitest::Mock.new(OpenStruct.new(
 706					registered?: OpenStruct.new(phone: old_tel),
 707					jid: Blather::JID.new(CONFIG[:sgx])
 708				))
 709
 710				target_customer = customer(sgx: sgx)
 711				admin = AdminCommand.for(target_customer, exe.customer_repo)
 712
 713				exe.customer_repo.expect(
 714					:find_by_jid,
 715					EMPromise.resolve(target_customer),
 716					[Matching.new do |jid|
 717						assert jid.is_a? Blather::JID
 718						assert_equal jid.stripped.to_s, "test@example.com"
 719					end]
 720				)
 721
 722				AdminAction::NumberChange::REDIS.expect(
 723					:rename,
 724					EMPromise.resolve(nil),
 725					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
 726				)
 727
 728				AdminAction::NumberChange::REDIS.expect(
 729					:get,
 730					EMPromise.resolve(nil),
 731					["jmp_customer_backend_sgx-test"]
 732				)
 733				AdminAction::NumberChange::REDIS.expect(
 734					:get,
 735					EMPromise.resolve(nil),
 736					["jmp_customer_backend_sgx-test"]
 737				)
 738
 739				BackendSgx::IQ_MANAGER.expect(
 740					:write,
 741					EMPromise.resolve(nil)
 742				) do |iq|
 743					assert_ibr_deregister_form(iq)
 744				end
 745
 746				BackendSgx::IQ_MANAGER.expect(
 747					:write,
 748					EMPromise.resolve(nil)
 749				) do |iq|
 750					assert_ibr_register_form(
 751						iq,
 752						"+12222222222"
 753					)
 754				end
 755
 756				AdminAction::NumberChange::REDIS.expect(
 757					:del,
 758					EMPromise.resolve(nil),
 759					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 760				)
 761
 762				BackendSgx::REDIS.expect(
 763					:set,
 764					EMPromise.resolve(nil),
 765					["catapult_jid-#{new_tel}", "customer_test@component"]
 766				)
 767
 768				Command::COMMAND_MANAGER.expect(
 769					:write,
 770					EMPromise.resolve(change_number_form(
 771						new_tel: "+12222222222"
 772					))
 773				) do |iq|
 774					assert_undoable_form(iq)
 775					assert_change_number_form(iq)
 776				end
 777
 778				expected_xadd_args = {
 779					customer_id: "test",
 780					old_tel: old_tel,
 781					new_tel: new_tel,
 782					should_delete: nil,
 783					actor_id: "test",
 784					class: "NumberChange",
 785					direction: :forward
 786				}.freeze
 787
 788				AdminActionRepo::REDIS.expect(
 789					:xadd,
 790					EMPromise.resolve(nil)
 791				) do |admin_actions, star, **xadd_args|
 792					assert_equal admin_actions, "admin_actions"
 793					assert_equal star, "*"
 794
 795					xadd_args.each do |k, v|
 796						assert_equal v, expected_xadd_args[k]
 797					end
 798				end
 799
 800				result = admin.action_number_change.sync
 801
 802				slug, backend_report, number_report = result.lines
 803
 804				assert_equal slug.strip, "Action : Change Number"
 805				assert_equal(
 806					backend_report.strip,
 807					"[move backend?]: sgx -> sgx"
 808				)
 809				assert_equal(
 810					number_report.strip,
 811					"[change number?]: +15556667777 -> +12222222222"
 812				)
 813
 814				assert_mock Command::COMMAND_MANAGER
 815				assert_mock exe.customer_repo
 816				assert_mock AdminAction::NumberChange::REDIS
 817				assert_mock AdminActionRepo::REDIS
 818				assert_mock BackendSgx::REDIS
 819				assert_mock BackendSgx::IQ_MANAGER
 820				assert_mock bandwidth_tn_repo_mock
 821				assert_mock sgx
 822			}
 823		end
 824	end
 825	em :test_change_num_different_num_same_backend
 826
 827	def test_change_num_same_num_different_backend
 828		target_backend_sgx = "route_value"
 829
 830		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 831			should_disconnect: false
 832		)
 833
 834		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 835			execute_command { |exe|
 836				sgx = Minitest::Mock.new(OpenStruct.new(
 837					registered?: OpenStruct.new(phone: "+15556667777"),
 838					jid: Blather::JID.new(CONFIG[:sgx])
 839				))
 840
 841				target_customer = customer(sgx: sgx)
 842				admin = AdminCommand.for(target_customer, exe.customer_repo)
 843
 844				exe.customer_repo.expect(
 845					:find_by_jid,
 846					EMPromise.resolve(target_customer),
 847					[Matching.new do |jid|
 848						assert jid.is_a? Blather::JID
 849						assert_equal jid.stripped.to_s, "test@example.com"
 850					end]
 851				)
 852
 853				Command::COMMAND_MANAGER.expect(
 854					:write,
 855					EMPromise.resolve(
 856						change_number_form(
 857							new_backend: target_backend_sgx
 858						)
 859					),
 860					[Matching.new do |iq|
 861						assert_undoable_form(iq)
 862						assert_change_number_form(iq)
 863					end]
 864				)
 865
 866				BackendSgx::IQ_MANAGER.expect(
 867					:write,
 868					EMPromise.resolve(nil)
 869				) do |iq|
 870					assert_ibr_deregister_form(iq)
 871				end
 872
 873				BackendSgx::IQ_MANAGER.expect(
 874					:write,
 875					EMPromise.resolve(nil)
 876				) do |iq|
 877					assert_ibr_register_form(
 878						iq,
 879						"+15556667777",
 880						target_backend_sgx: target_backend_sgx,
 881						nick: "test_sgx_account",
 882						username: "test_sgx_user",
 883						password: "test_sgx_password"
 884					)
 885				end
 886
 887				AdminAction::NumberChange::REDIS.expect(
 888					:get,
 889					EMPromise.resolve(nil),
 890					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 891				)
 892
 893				AdminAction::NumberChange::REDIS.expect(
 894					:set,
 895					EMPromise.resolve(nil),
 896					[
 897						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
 898						"route_value"
 899					]
 900				)
 901
 902				AdminAction::NumberChange::REDIS.expect(
 903					:get,
 904					EMPromise.resolve("route_value"),
 905					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 906				)
 907
 908				BackendSgx::REDIS.expect(
 909					:set,
 910					EMPromise.resolve(nil),
 911					[
 912						"catapult_jid-+15556667777",
 913						"customer_test@component"
 914					]
 915				)
 916
 917				expected_xadd_args = {
 918					old_tel: "+15556667777",
 919					new_tel: "+15556667777",
 920					old_backend: "sgx",
 921					new_backend: "route_value",
 922					should_delete: nil,
 923					actor_id: "test",
 924					class: "NumberChange",
 925					direction: :forward
 926				}.freeze
 927
 928				AdminActionRepo::REDIS.expect(
 929					:xadd,
 930					EMPromise.resolve(nil)
 931				) do |admin_actions, star, **xadd_args|
 932					assert_equal admin_actions, "admin_actions"
 933					assert_equal star, "*"
 934
 935					xadd_args.each do |k, v|
 936						assert_equal v, expected_xadd_args[k]
 937					end
 938				end
 939
 940				result = admin.action_number_change.sync
 941
 942				slug, backend_report, number_report = result.lines
 943
 944				assert_equal slug.strip, "Action : Change Number"
 945				assert_equal(
 946					backend_report.strip,
 947					"[move backend?]: sgx -> route_value"
 948				)
 949				assert_equal(
 950					number_report.strip,
 951					"[change number?]: +15556667777 -> +15556667777"
 952				)
 953
 954				assert_mock Command::COMMAND_MANAGER
 955				assert_mock exe.customer_repo
 956				assert_mock AdminAction::NumberChange::REDIS
 957				assert_mock AdminActionRepo::REDIS
 958				assert_mock BackendSgx::REDIS
 959				assert_mock BackendSgx::IQ_MANAGER
 960				assert_mock bandwidth_tn_repo_mock
 961				assert_mock sgx
 962			}
 963		end
 964	end
 965	em :test_change_num_same_num_different_backend
 966
 967	def test_change_num_different_num_different_backend
 968		old_tel = "+15556667777"
 969		new_tel = "+12222222222"
 970		target_backend_sgx = "route_value"
 971
 972		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 973			should_disconnect: false
 974		)
 975
 976		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 977			execute_command { |exe|
 978				sgx = Minitest::Mock.new(OpenStruct.new(
 979					registered?: OpenStruct.new(phone: old_tel),
 980					jid: Blather::JID.new(CONFIG[:sgx])
 981				))
 982
 983				target_customer = customer(sgx: sgx)
 984				admin = AdminCommand.for(target_customer, exe.customer_repo)
 985
 986				exe.customer_repo.expect(
 987					:find_by_jid,
 988					EMPromise.resolve(target_customer),
 989					[Matching.new do |jid|
 990						assert jid.is_a? Blather::JID
 991						assert_equal jid.stripped.to_s, "test@example.com"
 992					end]
 993				)
 994
 995				Command::COMMAND_MANAGER.expect(
 996					:write,
 997					EMPromise.resolve(
 998						change_number_form(
 999							new_tel: new_tel,
1000							new_backend: target_backend_sgx
1001						)
1002					),
1003					[Matching.new do |iq|
1004						assert_undoable_form(iq)
1005						assert_change_number_form(iq)
1006					end]
1007				)
1008
1009				BackendSgx::IQ_MANAGER.expect(
1010					:write,
1011					EMPromise.resolve(nil)
1012				) do |iq|
1013					assert_ibr_deregister_form(iq)
1014				end
1015
1016				BackendSgx::IQ_MANAGER.expect(
1017					:write,
1018					EMPromise.resolve(nil)
1019				) do |iq|
1020					assert_ibr_register_form(
1021						iq,
1022						"+12222222222",
1023						target_backend_sgx: target_backend_sgx,
1024						nick: "test_sgx_account",
1025						username: "test_sgx_user",
1026						password: "test_sgx_password"
1027					)
1028				end
1029
1030				AdminAction::NumberChange::REDIS.expect(
1031					:rename,
1032					EMPromise.resolve(nil),
1033					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1034				)
1035
1036				AdminAction::NumberChange::REDIS.expect(
1037					:get,
1038					EMPromise.resolve(nil),
1039					["jmp_customer_backend_sgx-test"]
1040				)
1041
1042				AdminAction::NumberChange::REDIS.expect(
1043					:set,
1044					EMPromise.resolve(nil),
1045					[
1046						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
1047						"route_value"
1048					]
1049				)
1050
1051				AdminAction::NumberChange::REDIS.expect(
1052					:get,
1053					EMPromise.resolve("route_value"),
1054					["jmp_customer_backend_sgx-test"]
1055				)
1056
1057				BackendSgx::REDIS.expect(
1058					:set,
1059					EMPromise.resolve(nil),
1060					[
1061						"catapult_jid-#{new_tel}",
1062						"customer_test@component"
1063					]
1064				)
1065
1066				expected_xadd_args = {
1067					old_tel: "+15556667777",
1068					new_tel: "+12222222222",
1069					target_backend_sgx: "route_value",
1070					should_delete: nil,
1071					actor_id: "test",
1072					class: "NumberChange",
1073					direction: :forward
1074				}.freeze
1075
1076				AdminActionRepo::REDIS.expect(
1077					:xadd,
1078					EMPromise.resolve(nil)
1079				) do |admin_actions, star, **xadd_args|
1080					assert_equal admin_actions, "admin_actions"
1081					assert_equal star, "*"
1082
1083					xadd_args.each do |k, v|
1084						assert_equal v, expected_xadd_args[k]
1085					end
1086				end
1087
1088				result = admin.action_number_change.sync
1089
1090				slug, backend_report, number_report = result.lines
1091
1092				assert_equal slug.strip, "Action : Change Number"
1093				assert_equal(
1094					backend_report.strip,
1095					"[move backend?]: sgx -> route_value"
1096				)
1097				assert_equal(
1098					number_report.strip,
1099					"[change number?]: +15556667777 -> +12222222222"
1100				)
1101
1102				assert_mock Command::COMMAND_MANAGER
1103				assert_mock exe.customer_repo
1104				assert_mock AdminAction::NumberChange::REDIS
1105				assert_mock AdminActionRepo::REDIS
1106				assert_mock BackendSgx::REDIS
1107				assert_mock BackendSgx::IQ_MANAGER
1108				assert_mock bandwidth_tn_repo_mock
1109				assert_mock sgx
1110			}
1111		end
1112	end
1113	em :test_change_num_different_num_different_backend
1114
1115	def test_change_num_bandwidth_backend_with_delete_should_disconnect
1116		old_tel = "+15556667777"
1117		new_tel = "+12222222222"
1118
1119		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
1120			should_disconnect: true,
1121			old_tel: old_tel,
1122			new_tel: new_tel
1123		)
1124
1125		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1126			execute_command { |exe|
1127				sgx = Minitest::Mock.new(OpenStruct.new(
1128					registered?: OpenStruct.new(phone: old_tel),
1129					jid: Blather::JID.new(CONFIG[:sgx])
1130				))
1131
1132				target_customer = customer(sgx: sgx)
1133				admin = AdminCommand.for(target_customer, exe.customer_repo)
1134
1135				exe.customer_repo.expect(
1136					:find_by_jid,
1137					EMPromise.resolve(customer(sgx: sgx)),
1138					[Matching.new do |jid|
1139						assert jid.is_a? Blather::JID
1140						assert_equal jid.stripped.to_s, "test@example.com"
1141					end]
1142				)
1143
1144				AdminAction::NumberChange::REDIS.expect(
1145					:rename,
1146					EMPromise.resolve(nil),
1147					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1148				)
1149
1150				expected_xadd_args = {
1151					customer_id: "test",
1152					old_tel: old_tel,
1153					new_tel: new_tel,
1154					should_delete: "true",
1155					actor_id: "test",
1156					class: "NumberChange",
1157					direction: :forward
1158				}.freeze
1159
1160				AdminActionRepo::REDIS.expect(
1161					:xadd,
1162					EMPromise.resolve(nil)
1163				) do |admin_actions, star, **xadd_args|
1164					assert_equal admin_actions, "admin_actions"
1165					assert_equal star, "*"
1166
1167					xadd_args.each do |k, v|
1168						assert_equal v, expected_xadd_args[k]
1169					end
1170				end
1171
1172				Command::COMMAND_MANAGER.expect(
1173					:write,
1174					EMPromise.resolve(
1175						change_number_form(
1176							new_tel: new_tel,
1177							should_delete: true
1178						)
1179					),
1180					[Matching.new do |iq|
1181						assert_undoable_form(iq)
1182						assert_change_number_form(iq)
1183					end]
1184				)
1185
1186				AdminAction::NumberChange::REDIS.expect(
1187					:get,
1188					EMPromise.resolve(nil),
1189					["jmp_customer_backend_sgx-test"]
1190				)
1191
1192				AdminAction::NumberChange::REDIS.expect(
1193					:del,
1194					EMPromise.resolve(nil),
1195					["jmp_customer_backend_sgx-test"]
1196				)
1197
1198				AdminAction::NumberChange::REDIS.expect(
1199					:get,
1200					EMPromise.resolve(nil),
1201					["jmp_customer_backend_sgx-test"]
1202				)
1203
1204				BackendSgx::REDIS.expect(
1205					:set,
1206					EMPromise.resolve(nil),
1207					[
1208						"catapult_jid-#{new_tel}",
1209						"customer_test@component"
1210					]
1211				)
1212
1213				BackendSgx::IQ_MANAGER.expect(
1214					:write,
1215					EMPromise.resolve(nil)
1216				) do |iq|
1217					assert_ibr_deregister_form(iq)
1218				end
1219
1220				BackendSgx::IQ_MANAGER.expect(
1221					:write,
1222					EMPromise.resolve(nil)
1223				) do |iq|
1224					assert_ibr_register_form(
1225						iq,
1226						new_tel,
1227						nick: "test_bw_account",
1228						username: "test_bw_user",
1229						password: "test_bw_password"
1230					)
1231				end
1232
1233				result = admin.action_number_change.sync
1234
1235				slug, backend_report, number_report = result.lines
1236
1237				assert_equal slug.strip, "Action : Change Number"
1238				assert_equal(
1239					backend_report.strip,
1240					"[move backend?]: sgx -> sgx"
1241				)
1242				assert_equal(
1243					number_report.strip,
1244					"[change number?]: #{old_tel} -> #{new_tel}"
1245				)
1246
1247				assert_mock Command::COMMAND_MANAGER
1248				assert_mock exe.customer_repo
1249				assert_mock AdminAction::NumberChange::REDIS
1250				assert_mock AdminActionRepo::REDIS
1251				assert_mock BackendSgx::REDIS
1252				assert_mock BackendSgx::IQ_MANAGER
1253				assert_mock bandwidth_tn_repo_mock
1254				assert_mock sgx
1255			}
1256		end
1257	end
1258	em :test_change_num_bandwidth_backend_with_delete_should_disconnect
1259
1260	def test_change_num_non_bw_backend_should_not_disconnect
1261		old_tel = "+15556667777"
1262		new_tel = "+12222222222"
1263		non_bw_backend = "route_value"
1264
1265		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
1266			should_disconnect: false
1267		)
1268
1269		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1270			execute_command { |exe|
1271				Command::COMMAND_MANAGER.expect(
1272					:write,
1273					EMPromise.resolve(change_number_form(new_tel: new_tel)),
1274					[Matching.new do |iq|
1275						assert_undoable_form(iq)
1276						assert_change_number_form(iq)
1277					end]
1278				)
1279
1280				non_bandwidth_sgx = Minitest::Mock.new(OpenStruct.new(
1281					registered?: OpenStruct.new(phone: old_tel),
1282					jid: Blather::JID.new(non_bw_backend)
1283				))
1284
1285				target_customer = customer(sgx: non_bandwidth_sgx)
1286				admin = AdminCommand.for(target_customer, exe.customer_repo)
1287
1288				exe.customer_repo.expect(
1289					:find_by_jid,
1290					EMPromise.resolve(target_customer),
1291					[Blather::JID.new("test@example.com")]
1292				)
1293
1294				AdminAction::NumberChange::REDIS.expect(
1295					:rename,
1296					EMPromise.resolve(nil),
1297					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1298				)
1299
1300				AdminAction::NumberChange::REDIS.expect(
1301					:get,
1302					EMPromise.resolve("route_value"),
1303					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1304				)
1305
1306				BackendSgx::IQ_MANAGER.expect(
1307					:write,
1308					EMPromise.resolve(nil)
1309				) do |iq|
1310					assert_ibr_deregister_form(
1311						iq,
1312						target_backend_sgx: "route_value"
1313					)
1314				end
1315
1316				AdminAction::NumberChange::REDIS.expect(
1317					:set,
1318					EMPromise.resolve(nil),
1319					[
1320						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
1321						"route_value"
1322					]
1323				)
1324
1325				AdminAction::NumberChange::REDIS.expect(
1326					:get,
1327					EMPromise.resolve("route_value"),
1328					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1329				)
1330
1331				BackendSgx::IQ_MANAGER.expect(
1332					:write,
1333					EMPromise.resolve(nil)
1334				) do |iq|
1335					assert_ibr_register_form(
1336						iq,
1337						"+12222222222",
1338						nick: "test_sgx_account",
1339						username: "test_sgx_user",
1340						password: "test_sgx_password",
1341						target_backend_sgx: "route_value"
1342					)
1343				end
1344
1345				BackendSgx::REDIS.expect(
1346					:set,
1347					EMPromise.resolve(nil),
1348					["catapult_jid-+12222222222", "customer_test@component"]
1349				)
1350
1351				expected_xadd_args = {
1352					customer_id: "test",
1353					old_tel: old_tel,
1354					new_tel: new_tel,
1355					should_delete: "true",
1356					actor_id: "test",
1357					class: "NumberChange",
1358					direction: :forward
1359				}.freeze
1360
1361				AdminActionRepo::REDIS.expect(
1362					:xadd,
1363					EMPromise.resolve(nil)
1364				) do |admin_actions, star, **xadd_args|
1365					assert_equal admin_actions, "admin_actions"
1366					assert_equal star, "*"
1367
1368					xadd_args.each do |k, v|
1369						assert_equal v, expected_xadd_args[k]
1370					end
1371				end
1372
1373				result = admin.action_number_change.sync
1374
1375				slug, backend_report, number_report = result.lines
1376
1377				assert_equal slug.strip, "Action : Change Number"
1378				assert_equal(
1379					backend_report.strip,
1380					"[move backend?]: #{non_bw_backend} -> #{non_bw_backend}"
1381				)
1382				assert_equal(
1383					number_report.strip,
1384					"[change number?]: +15556667777 -> +12222222222"
1385				)
1386
1387				assert_mock Command::COMMAND_MANAGER
1388				assert_mock exe.customer_repo
1389				assert_mock AdminAction::NumberChange::REDIS
1390				assert_mock AdminActionRepo::REDIS
1391				assert_mock BackendSgx::REDIS
1392				assert_mock BackendSgx::IQ_MANAGER
1393				assert_mock bandwidth_tn_repo_mock
1394				assert_mock non_bandwidth_sgx
1395			}
1396		end
1397	end
1398	em :test_change_num_non_bw_backend_should_not_disconnect
1399end