test_admin_command.rb

   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		execute_command { |exe|
 433			sgx = Minitest::Mock.new(OpenStruct.new(
 434				registered?: nil,
 435				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 436			))
 437			target_customer = customer(sgx: sgx)
 438			admin = AdminCommand.for(target_customer, exe.customer_repo)
 439
 440			error = assert_raises(
 441				"number change for unregistered customer should raise"
 442			) {
 443				admin.action_number_change.sync
 444			}
 445
 446			assert_equal error.to_s, "Customer not registered"
 447		}
 448	end
 449	em :test_change_num_for_unregistered_customer
 450
 451	def test_change_num_same_num_same_backend
 452		# Same as default given by `sgx.registered?` returned by `admin_command`
 453		tel = "+15556667777"
 454
 455		execute_command { |exe|
 456			sgx = Minitest::Mock.new(OpenStruct.new(
 457				registered?: OpenStruct.new(phone: tel),
 458				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 459			))
 460
 461			target_customer = customer(sgx: sgx)
 462			admin = AdminCommand.for(target_customer, exe.customer_repo)
 463
 464			exe.customer_repo.expect(
 465				:find_by_jid,
 466				EMPromise.resolve(target_customer),
 467				[Matching.new do |jid|
 468					assert jid.is_a? Blather::JID
 469					assert_equal jid.stripped.to_s, "test@example.com"
 470				end]
 471			)
 472
 473			AdminAction::NumberChange::REDIS.expect(
 474				:exists,
 475				EMPromise.resolve(1),
 476				["catapult_jid-#{tel}"]
 477			)
 478
 479			Command::COMMAND_MANAGER.expect(
 480				:write,
 481				EMPromise.resolve(change_number_form(
 482					new_tel: tel,
 483					new_backend: "sgx"
 484				)),
 485				[Matching.new do |iq|
 486					assert_undoable_form(iq)
 487					assert_change_number_form(iq)
 488				end]
 489			)
 490
 491			error = admin.action_number_change
 492				.catch_only(AdminAction::NoOp) { |e| e }.sync
 493
 494			assert error.is_a?(AdminAction::NoOp)
 495			assert_mock Command::COMMAND_MANAGER
 496			assert_mock exe.customer_repo
 497			assert_mock AdminAction::NumberChange::REDIS
 498			assert_mock sgx
 499		}
 500	end
 501	em :test_change_num_same_num_same_backend
 502
 503	def test_change_num_blank_num_blank_backend
 504		# Same as default given by `sgx.registered?` returned by `admin_command`
 505		tel = "+15556667777"
 506
 507		execute_command { |exe|
 508			sgx = Minitest::Mock.new(OpenStruct.new(
 509				registered?: OpenStruct.new(phone: tel),
 510				jid: Blather::JID.new(CONFIG[:sgx]) # Uses Bandwidth backend
 511			))
 512
 513			target_customer = customer(sgx: sgx)
 514
 515			admin = AdminCommand.for(target_customer, exe.customer_repo)
 516
 517			exe.customer_repo.expect(
 518				:find_by_jid,
 519				EMPromise.resolve(target_customer),
 520				[Matching.new do |jid|
 521					assert jid.is_a? Blather::JID
 522					assert_equal jid.stripped.to_s, "test@example.com"
 523				end]
 524			)
 525
 526			AdminAction::NumberChange::REDIS.expect(
 527				:exists,
 528				EMPromise.resolve(1),
 529				["catapult_jid-#{tel}"]
 530			)
 531
 532			Command::COMMAND_MANAGER.expect(
 533				:write,
 534				EMPromise.resolve(change_number_form),
 535				[Matching.new do |iq|
 536					assert_undoable_form(iq)
 537					assert_change_number_form(iq)
 538				end]
 539			)
 540
 541			error = admin.action_number_change
 542				.catch_only(AdminAction::NoOp) { |e| e }.sync
 543
 544			assert error.is_a?(AdminAction::NoOp)
 545			assert_mock Command::COMMAND_MANAGER
 546			assert_mock exe.customer_repo
 547			assert_mock AdminAction::NumberChange::REDIS
 548			assert_mock sgx
 549		}
 550	end
 551	em :test_change_num_blank_num_blank_backend
 552
 553	def test_change_num_different_num_same_backend
 554		old_tel = "+15556667777"
 555		new_tel = "+12222222222"
 556		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 557			should_disconnect: false
 558		)
 559
 560		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 561			execute_command { |exe|
 562				sgx = Minitest::Mock.new(OpenStruct.new(
 563					registered?: OpenStruct.new(phone: old_tel),
 564					jid: Blather::JID.new(CONFIG[:sgx])
 565				))
 566
 567				target_customer = customer(sgx: sgx)
 568				admin = AdminCommand.for(target_customer, exe.customer_repo)
 569
 570				exe.customer_repo.expect(
 571					:find_by_jid,
 572					EMPromise.resolve(target_customer),
 573					[Matching.new do |jid|
 574						assert jid.is_a? Blather::JID
 575						assert_equal jid.stripped.to_s, "test@example.com"
 576					end]
 577				)
 578
 579				AdminAction::NumberChange::REDIS.expect(
 580					:rename,
 581					EMPromise.resolve(nil),
 582					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
 583				)
 584
 585				AdminAction::NumberChange::REDIS.expect(
 586					:get,
 587					EMPromise.resolve(nil),
 588					["jmp_customer_backend_sgx-test"]
 589				)
 590				AdminAction::NumberChange::REDIS.expect(
 591					:get,
 592					EMPromise.resolve(nil),
 593					["jmp_customer_backend_sgx-test"]
 594				)
 595
 596				BackendSgx::IQ_MANAGER.expect(
 597					:write,
 598					EMPromise.resolve(nil)
 599				) do |iq|
 600					assert_ibr_deregister_form(iq)
 601				end
 602
 603				BackendSgx::IQ_MANAGER.expect(
 604					:write,
 605					EMPromise.resolve(nil)
 606				) do |iq|
 607					assert_ibr_register_form(
 608						iq,
 609						"+12222222222"
 610					)
 611				end
 612
 613				AdminAction::NumberChange::REDIS.expect(
 614					:del,
 615					EMPromise.resolve(nil),
 616					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 617				)
 618
 619				BackendSgx::REDIS.expect(
 620					:set,
 621					EMPromise.resolve(nil),
 622					["catapult_jid-#{new_tel}", "customer_test@component"]
 623				)
 624
 625				AdminAction::NumberChange::REDIS.expect(
 626					:exists,
 627					EMPromise.resolve(1),
 628					["catapult_jid-#{old_tel}"]
 629				)
 630
 631				Command::COMMAND_MANAGER.expect(
 632					:write,
 633					EMPromise.resolve(change_number_form(
 634						new_tel: "+12222222222"
 635					))
 636				) do |iq|
 637					assert_undoable_form(iq)
 638					assert_change_number_form(iq)
 639				end
 640
 641				expected_xadd_args = {
 642					customer_id: "test",
 643					old_tel: old_tel,
 644					new_tel: new_tel,
 645					should_delete: nil,
 646					actor_id: "test",
 647					class: "NumberChange",
 648					direction: :forward
 649				}.freeze
 650
 651				AdminActionRepo::REDIS.expect(
 652					:xadd,
 653					EMPromise.resolve(nil)
 654				) do |admin_actions, star, **xadd_args|
 655					assert_equal admin_actions, "admin_actions"
 656					assert_equal star, "*"
 657
 658					xadd_args.each do |k, v|
 659						assert_equal v, expected_xadd_args[k]
 660					end
 661				end
 662
 663				result = admin.action_number_change.sync
 664
 665				slug, backend_report, number_report = result.lines
 666
 667				assert_equal slug.strip, "Action : Change Number"
 668				assert_equal(
 669					backend_report.strip,
 670					"[move backend?]: sgx -> sgx"
 671				)
 672				assert_equal(
 673					number_report.strip,
 674					"[change number?]: +15556667777 -> +12222222222"
 675				)
 676
 677				assert_mock Command::COMMAND_MANAGER
 678				assert_mock exe.customer_repo
 679				assert_mock AdminAction::NumberChange::REDIS
 680				assert_mock AdminActionRepo::REDIS
 681				assert_mock BackendSgx::REDIS
 682				assert_mock BackendSgx::IQ_MANAGER
 683				assert_mock bandwidth_tn_repo_mock
 684				assert_mock sgx
 685			}
 686		end
 687	end
 688	em :test_change_num_different_num_same_backend
 689
 690	def test_change_num_same_num_different_backend
 691		target_backend_sgx = "route_value"
 692
 693		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 694			should_disconnect: false
 695		)
 696
 697		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 698			execute_command { |exe|
 699				sgx = Minitest::Mock.new(OpenStruct.new(
 700					registered?: OpenStruct.new(phone: "+15556667777"),
 701					jid: Blather::JID.new(CONFIG[:sgx])
 702				))
 703
 704				target_customer = customer(sgx: sgx)
 705				admin = AdminCommand.for(target_customer, exe.customer_repo)
 706
 707				exe.customer_repo.expect(
 708					:find_by_jid,
 709					EMPromise.resolve(target_customer),
 710					[Matching.new do |jid|
 711						assert jid.is_a? Blather::JID
 712						assert_equal jid.stripped.to_s, "test@example.com"
 713					end]
 714				)
 715
 716				Command::COMMAND_MANAGER.expect(
 717					:write,
 718					EMPromise.resolve(
 719						change_number_form(
 720							new_backend: target_backend_sgx
 721						)
 722					),
 723					[Matching.new do |iq|
 724						assert_undoable_form(iq)
 725						assert_change_number_form(iq)
 726					end]
 727				)
 728
 729				BackendSgx::IQ_MANAGER.expect(
 730					:write,
 731					EMPromise.resolve(nil)
 732				) do |iq|
 733					assert_ibr_deregister_form(iq)
 734				end
 735
 736				BackendSgx::IQ_MANAGER.expect(
 737					:write,
 738					EMPromise.resolve(nil)
 739				) do |iq|
 740					assert_ibr_register_form(
 741						iq,
 742						"+15556667777",
 743						target_backend_sgx: target_backend_sgx,
 744						nick: "test_sgx_account",
 745						username: "test_sgx_user",
 746						password: "test_sgx_password"
 747					)
 748				end
 749
 750				AdminAction::NumberChange::REDIS.expect(
 751					:get,
 752					EMPromise.resolve(nil),
 753					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 754				)
 755
 756				AdminAction::NumberChange::REDIS.expect(
 757					:set,
 758					EMPromise.resolve(nil),
 759					[
 760						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
 761						"route_value"
 762					]
 763				)
 764
 765				AdminAction::NumberChange::REDIS.expect(
 766					:get,
 767					EMPromise.resolve("route_value"),
 768					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
 769				)
 770
 771				AdminAction::NumberChange::REDIS.expect(
 772					:exists,
 773					EMPromise.resolve(1),
 774					["catapult_jid-+15556667777"]
 775				)
 776
 777				BackendSgx::REDIS.expect(
 778					:set,
 779					EMPromise.resolve(nil),
 780					[
 781						"catapult_jid-+15556667777",
 782						"customer_test@component"
 783					]
 784				)
 785
 786				expected_xadd_args = {
 787					old_tel: "+15556667777",
 788					new_tel: "+15556667777",
 789					old_backend: "sgx",
 790					new_backend: "route_value",
 791					should_delete: nil,
 792					actor_id: "test",
 793					class: "NumberChange",
 794					direction: :forward
 795				}.freeze
 796
 797				AdminActionRepo::REDIS.expect(
 798					:xadd,
 799					EMPromise.resolve(nil)
 800				) do |admin_actions, star, **xadd_args|
 801					assert_equal admin_actions, "admin_actions"
 802					assert_equal star, "*"
 803
 804					xadd_args.each do |k, v|
 805						assert_equal v, expected_xadd_args[k]
 806					end
 807				end
 808
 809				result = admin.action_number_change.sync
 810
 811				slug, backend_report, number_report = result.lines
 812
 813				assert_equal slug.strip, "Action : Change Number"
 814				assert_equal(
 815					backend_report.strip,
 816					"[move backend?]: sgx -> route_value"
 817				)
 818				assert_equal(
 819					number_report.strip,
 820					"[change number?]: +15556667777 -> +15556667777"
 821				)
 822
 823				assert_mock Command::COMMAND_MANAGER
 824				assert_mock exe.customer_repo
 825				assert_mock AdminAction::NumberChange::REDIS
 826				assert_mock AdminActionRepo::REDIS
 827				assert_mock BackendSgx::REDIS
 828				assert_mock BackendSgx::IQ_MANAGER
 829				assert_mock bandwidth_tn_repo_mock
 830				assert_mock sgx
 831			}
 832		end
 833	end
 834	em :test_change_num_same_num_different_backend
 835
 836	def test_change_num_different_num_different_backend
 837		old_tel = "+15556667777"
 838		new_tel = "+12222222222"
 839		target_backend_sgx = "route_value"
 840
 841		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 842			should_disconnect: false
 843		)
 844
 845		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
 846			execute_command { |exe|
 847				sgx = Minitest::Mock.new(OpenStruct.new(
 848					registered?: OpenStruct.new(phone: old_tel),
 849					jid: Blather::JID.new(CONFIG[:sgx])
 850				))
 851
 852				target_customer = customer(sgx: sgx)
 853				admin = AdminCommand.for(target_customer, exe.customer_repo)
 854
 855				exe.customer_repo.expect(
 856					:find_by_jid,
 857					EMPromise.resolve(target_customer),
 858					[Matching.new do |jid|
 859						assert jid.is_a? Blather::JID
 860						assert_equal jid.stripped.to_s, "test@example.com"
 861					end]
 862				)
 863
 864				Command::COMMAND_MANAGER.expect(
 865					:write,
 866					EMPromise.resolve(
 867						change_number_form(
 868							new_tel: new_tel,
 869							new_backend: target_backend_sgx
 870						)
 871					),
 872					[Matching.new do |iq|
 873						assert_undoable_form(iq)
 874						assert_change_number_form(iq)
 875					end]
 876				)
 877
 878				BackendSgx::IQ_MANAGER.expect(
 879					:write,
 880					EMPromise.resolve(nil)
 881				) do |iq|
 882					assert_ibr_deregister_form(iq)
 883				end
 884
 885				BackendSgx::IQ_MANAGER.expect(
 886					:write,
 887					EMPromise.resolve(nil)
 888				) do |iq|
 889					assert_ibr_register_form(
 890						iq,
 891						"+12222222222",
 892						target_backend_sgx: target_backend_sgx,
 893						nick: "test_sgx_account",
 894						username: "test_sgx_user",
 895						password: "test_sgx_password"
 896					)
 897				end
 898
 899				AdminAction::NumberChange::REDIS.expect(
 900					:exists,
 901					EMPromise.resolve(1),
 902					["catapult_jid-#{old_tel}"]
 903				)
 904
 905				AdminAction::NumberChange::REDIS.expect(
 906					:rename,
 907					EMPromise.resolve(nil),
 908					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
 909				)
 910
 911				AdminAction::NumberChange::REDIS.expect(
 912					:get,
 913					EMPromise.resolve(nil),
 914					["jmp_customer_backend_sgx-test"]
 915				)
 916
 917				AdminAction::NumberChange::REDIS.expect(
 918					:set,
 919					EMPromise.resolve(nil),
 920					[
 921						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
 922						"route_value"
 923					]
 924				)
 925
 926				AdminAction::NumberChange::REDIS.expect(
 927					:get,
 928					EMPromise.resolve("route_value"),
 929					["jmp_customer_backend_sgx-test"]
 930				)
 931
 932				BackendSgx::REDIS.expect(
 933					:set,
 934					EMPromise.resolve(nil),
 935					[
 936						"catapult_jid-#{new_tel}",
 937						"customer_test@component"
 938					]
 939				)
 940
 941				expected_xadd_args = {
 942					old_tel: "+15556667777",
 943					new_tel: "+12222222222",
 944					target_backend_sgx: "route_value",
 945					should_delete: nil,
 946					actor_id: "test",
 947					class: "NumberChange",
 948					direction: :forward
 949				}.freeze
 950
 951				AdminActionRepo::REDIS.expect(
 952					:xadd,
 953					EMPromise.resolve(nil)
 954				) do |admin_actions, star, **xadd_args|
 955					assert_equal admin_actions, "admin_actions"
 956					assert_equal star, "*"
 957
 958					xadd_args.each do |k, v|
 959						assert_equal v, expected_xadd_args[k]
 960					end
 961				end
 962
 963				result = admin.action_number_change.sync
 964
 965				slug, backend_report, number_report = result.lines
 966
 967				assert_equal slug.strip, "Action : Change Number"
 968				assert_equal(
 969					backend_report.strip,
 970					"[move backend?]: sgx -> route_value"
 971				)
 972				assert_equal(
 973					number_report.strip,
 974					"[change number?]: +15556667777 -> +12222222222"
 975				)
 976
 977				assert_mock Command::COMMAND_MANAGER
 978				assert_mock exe.customer_repo
 979				assert_mock AdminAction::NumberChange::REDIS
 980				assert_mock AdminActionRepo::REDIS
 981				assert_mock BackendSgx::REDIS
 982				assert_mock BackendSgx::IQ_MANAGER
 983				assert_mock bandwidth_tn_repo_mock
 984				assert_mock sgx
 985			}
 986		end
 987	end
 988	em :test_change_num_different_num_different_backend
 989
 990	def test_change_num_bandwidth_backend_with_delete_should_disconnect
 991		old_tel = "+15556667777"
 992		new_tel = "+12222222222"
 993
 994		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
 995			should_disconnect: true,
 996			old_tel: old_tel,
 997			new_tel: new_tel
 998		)
 999
1000		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1001			execute_command { |exe|
1002				sgx = Minitest::Mock.new(OpenStruct.new(
1003					registered?: OpenStruct.new(phone: old_tel),
1004					jid: Blather::JID.new(CONFIG[:sgx])
1005				))
1006
1007				target_customer = customer(sgx: sgx)
1008				admin = AdminCommand.for(target_customer, exe.customer_repo)
1009
1010				exe.customer_repo.expect(
1011					:find_by_jid,
1012					EMPromise.resolve(customer(sgx: sgx)),
1013					[Matching.new do |jid|
1014						assert jid.is_a? Blather::JID
1015						assert_equal jid.stripped.to_s, "test@example.com"
1016					end]
1017				)
1018
1019				AdminAction::NumberChange::REDIS.expect(
1020					:exists,
1021					EMPromise.resolve(1),
1022					["catapult_jid-#{old_tel}"]
1023				)
1024
1025				AdminAction::NumberChange::REDIS.expect(
1026					:rename,
1027					EMPromise.resolve(nil),
1028					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1029				)
1030
1031				expected_xadd_args = {
1032					customer_id: "test",
1033					old_tel: old_tel,
1034					new_tel: new_tel,
1035					should_delete: "true",
1036					actor_id: "test",
1037					class: "NumberChange",
1038					direction: :forward
1039				}.freeze
1040
1041				AdminActionRepo::REDIS.expect(
1042					:xadd,
1043					EMPromise.resolve(nil)
1044				) do |admin_actions, star, **xadd_args|
1045					assert_equal admin_actions, "admin_actions"
1046					assert_equal star, "*"
1047
1048					xadd_args.each do |k, v|
1049						assert_equal v, expected_xadd_args[k]
1050					end
1051				end
1052
1053				Command::COMMAND_MANAGER.expect(
1054					:write,
1055					EMPromise.resolve(
1056						change_number_form(
1057							new_tel: new_tel,
1058							should_delete: true
1059						)
1060					),
1061					[Matching.new do |iq|
1062						assert_undoable_form(iq)
1063						assert_change_number_form(iq)
1064					end]
1065				)
1066
1067				AdminAction::NumberChange::REDIS.expect(
1068					:get,
1069					EMPromise.resolve(nil),
1070					["jmp_customer_backend_sgx-test"]
1071				)
1072
1073				AdminAction::NumberChange::REDIS.expect(
1074					:del,
1075					EMPromise.resolve(nil),
1076					["jmp_customer_backend_sgx-test"]
1077				)
1078
1079				AdminAction::NumberChange::REDIS.expect(
1080					:get,
1081					EMPromise.resolve(nil),
1082					["jmp_customer_backend_sgx-test"]
1083				)
1084
1085				BackendSgx::REDIS.expect(
1086					:set,
1087					EMPromise.resolve(nil),
1088					[
1089						"catapult_jid-#{new_tel}",
1090						"customer_test@component"
1091					]
1092				)
1093
1094				BackendSgx::IQ_MANAGER.expect(
1095					:write,
1096					EMPromise.resolve(nil)
1097				) do |iq|
1098					assert_ibr_deregister_form(iq)
1099				end
1100
1101				BackendSgx::IQ_MANAGER.expect(
1102					:write,
1103					EMPromise.resolve(nil)
1104				) do |iq|
1105					assert_ibr_register_form(
1106						iq,
1107						new_tel,
1108						nick: "test_bw_account",
1109						username: "test_bw_user",
1110						password: "test_bw_password"
1111					)
1112				end
1113
1114				result = admin.action_number_change.sync
1115
1116				slug, backend_report, number_report = result.lines
1117
1118				assert_equal slug.strip, "Action : Change Number"
1119				assert_equal(
1120					backend_report.strip,
1121					"[move backend?]: sgx -> sgx"
1122				)
1123				assert_equal(
1124					number_report.strip,
1125					"[change number?]: #{old_tel} -> #{new_tel}"
1126				)
1127
1128				assert_mock Command::COMMAND_MANAGER
1129				assert_mock exe.customer_repo
1130				assert_mock AdminAction::NumberChange::REDIS
1131				assert_mock AdminActionRepo::REDIS
1132				assert_mock BackendSgx::REDIS
1133				assert_mock BackendSgx::IQ_MANAGER
1134				assert_mock bandwidth_tn_repo_mock
1135				assert_mock sgx
1136			}
1137		end
1138	end
1139	em :test_change_num_bandwidth_backend_with_delete_should_disconnect
1140
1141	def test_change_num_non_bw_backend_should_not_disconnect
1142		old_tel = "+15556667777"
1143		new_tel = "+12222222222"
1144		non_bw_backend = "route_value"
1145
1146		bandwidth_tn_repo_mock = setup_bandwidth_tn_repo_mock(
1147			should_disconnect: false
1148		)
1149
1150		BandwidthTnRepo.stub :new, bandwidth_tn_repo_mock do
1151			execute_command { |exe|
1152				Command::COMMAND_MANAGER.expect(
1153					:write,
1154					EMPromise.resolve(change_number_form(new_tel: new_tel)),
1155					[Matching.new do |iq|
1156						assert_undoable_form(iq)
1157						assert_change_number_form(iq)
1158					end]
1159				)
1160
1161				non_bandwidth_sgx = Minitest::Mock.new(OpenStruct.new(
1162					registered?: OpenStruct.new(phone: old_tel),
1163					jid: Blather::JID.new(non_bw_backend)
1164				))
1165
1166				target_customer = customer(sgx: non_bandwidth_sgx)
1167				admin = AdminCommand.for(target_customer, exe.customer_repo)
1168
1169				exe.customer_repo.expect(
1170					:find_by_jid,
1171					EMPromise.resolve(target_customer),
1172					[Blather::JID.new("test@example.com")]
1173				)
1174
1175				AdminAction::NumberChange::REDIS.expect(
1176					:exists,
1177					EMPromise.resolve(1),
1178					["catapult_jid-+15556667777"]
1179				)
1180
1181				AdminAction::NumberChange::REDIS.expect(
1182					:rename,
1183					EMPromise.resolve(nil),
1184					["catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"]
1185				)
1186
1187				AdminAction::NumberChange::REDIS.expect(
1188					:get,
1189					EMPromise.resolve("route_value"),
1190					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1191				)
1192
1193				BackendSgx::IQ_MANAGER.expect(
1194					:write,
1195					EMPromise.resolve(nil)
1196				) do |iq|
1197					assert_ibr_deregister_form(
1198						iq,
1199						target_backend_sgx: "route_value"
1200					)
1201				end
1202
1203				AdminAction::NumberChange::REDIS.expect(
1204					:set,
1205					EMPromise.resolve(nil),
1206					[
1207						"jmp_customer_backend_sgx-#{target_customer.customer_id}",
1208						"route_value"
1209					]
1210				)
1211
1212				AdminAction::NumberChange::REDIS.expect(
1213					:get,
1214					EMPromise.resolve("route_value"),
1215					["jmp_customer_backend_sgx-#{target_customer.customer_id}"]
1216				)
1217
1218				BackendSgx::IQ_MANAGER.expect(
1219					:write,
1220					EMPromise.resolve(nil)
1221				) do |iq|
1222					assert_ibr_register_form(
1223						iq,
1224						"+12222222222",
1225						nick: "test_sgx_account",
1226						username: "test_sgx_user",
1227						password: "test_sgx_password",
1228						target_backend_sgx: "route_value"
1229					)
1230				end
1231
1232				BackendSgx::REDIS.expect(
1233					:set,
1234					EMPromise.resolve(nil),
1235					["catapult_jid-+12222222222", "customer_test@component"]
1236				)
1237
1238				expected_xadd_args = {
1239					customer_id: "test",
1240					old_tel: old_tel,
1241					new_tel: new_tel,
1242					should_delete: "true",
1243					actor_id: "test",
1244					class: "NumberChange",
1245					direction: :forward
1246				}.freeze
1247
1248				AdminActionRepo::REDIS.expect(
1249					:xadd,
1250					EMPromise.resolve(nil)
1251				) do |admin_actions, star, **xadd_args|
1252					assert_equal admin_actions, "admin_actions"
1253					assert_equal star, "*"
1254
1255					xadd_args.each do |k, v|
1256						assert_equal v, expected_xadd_args[k]
1257					end
1258				end
1259
1260				result = admin.action_number_change.sync
1261
1262				slug, backend_report, number_report = result.lines
1263
1264				assert_equal slug.strip, "Action : Change Number"
1265				assert_equal(
1266					backend_report.strip,
1267					"[move backend?]: #{non_bw_backend} -> #{non_bw_backend}"
1268				)
1269				assert_equal(
1270					number_report.strip,
1271					"[change number?]: +15556667777 -> +12222222222"
1272				)
1273
1274				assert_mock Command::COMMAND_MANAGER
1275				assert_mock exe.customer_repo
1276				assert_mock AdminAction::NumberChange::REDIS
1277				assert_mock AdminActionRepo::REDIS
1278				assert_mock BackendSgx::REDIS
1279				assert_mock BackendSgx::IQ_MANAGER
1280				assert_mock bandwidth_tn_repo_mock
1281				assert_mock non_bandwidth_sgx
1282			}
1283		end
1284	end
1285	em :test_change_num_non_bw_backend_should_not_disconnect
1286end